Event Handler губи събитие във Firefox, когато AJAX DHTML

Имам проблем с манипулатор на събития, използван за прибягване на таблица с клавиша табулация, поставящ въведена клетка или поле за избор в нея, за да редактирате данни в MySQL

Методът се улавя от манипулатора на събития, натиснатият клавиш се валидира, ако TAB, той ще продължи с валидирането на данните, ако е валиден, достига базата данни, за да актуализира търсенето на следващата валидна клетка, за да вмъкне или nput, или поле за избор.

Проблемът е, че кодът не работи във Firefox. Когато редът свърши и трябва да вмъкне полето за избор, манипулаторът на събитие изглежда губи събитието и следващият фокусиран елемент прескача към следващия елемент, губейки функцията на манипулатора на събитие.

Тествайки с firebug Открих, че кодът се прекъсва във функцията за манипулиране на ключове, когато елементът, който задейства събитието, е заменен с текстова стойност. По-странно е, че ajax елементът (списък за избор), който трябва да бъде вмъкнат динамично, се появява за момент на екрана и след това изчезва. След това се опитах да премахна елемента с метода removeChild и след това да вмъкна с innerHTML, но все още не работи.

        The table code
        <p style='text-align:center'>
        <legend><strong>PRODUTOS</strong></legend></p>

        <table class='resultados' id='produtos'>
          <tr><th style='display:none'>Código</th>
            <th style='text-align:right'>Grupo</th>
            <th style='text-align:center'>Marca</th>
            <th>Descrição</th>
            <th style='text-align:right'>Preço sugerido</th>
            <th><img src='../../../imagens/detalhes/detalhes.png' /></th>
            <th><img src='../../../imagens/img.png' /></th>
            <th><img src='../../../imagens/apaga/apaga.png' /></th>
          </tr>

        <tr class='alt'>
        <td style='display:none' id='codproduto1' title='codproduto'>79</td>

        <td style='text-align:right' title='Grupo' name='descgrupo' id='descgrupo1' onclick='adlg(this);' >ATUALIZAÇÕES</td>

        <td style='text-align:center' title='Marca' name='marca' id='marca1' onclick='adinp(this);'  >    MARCA</td>

        <td title='Descrição' name='descproduto' id='descproduto1' onclick='adinp(this);' >PRODUTO</td>

        <td style='text-align:right' title='Preço sugerido' name='precos' id='precos1' onclick='adinp(this);' >12,00</td>

        <td style='text-align:center' title='Detalhes Produto' id='detfila1' ><input type='image' src='../../../imagens/detalhes/detalhes.png'  onclick='exdetp(this);' /></td>

        <td style='text-align:center' title='Imagem Produto' id='imgfila1' ><input type='image'  src='../../../imagens/img.png' onclick='imgProduto(this);' /></td>

        <td style='text-align:center' title='Apagar Fila' id='apfila1' ><input type='image' src='../../../imagens/apaga/apaga.png' onclick='apProduto(this);' /></td>
    </tr>

        <tr class=''>
        <td style='display:none' id='codproduto2' title='codproduto'>81</td>
        <td style='text-align:right' title='Grupo' name='descgrupo' id='descgrupo2' onclick='adlg(this);' >ATUALIZAÇÕES</td>

        <td style='text-align:center' title='Marca' name='marca' id='marca2' onclick='adinp(this);'  >MARCA</td>

        <td title='Descrição' name='descproduto' id='descproduto2' onclick='adinp(this);' >PRODUTO2</td>

        <td style='text-align:right' title='Preço sugerido' name='precos' id='precos2' onclick='adinp(this);' >54,00</td>

        <td style='text-align:center' title='Detalhes Produto' id='detfila2' ><input type='image' src='../../../imagens/detalhes/detalhes.png'  onclick='exdetp(this);' /></td>

        <td style='text-align:center' title='Imagem Produto' id='imgfila2' ><input type='image' src='../../../imagens/img.png' onclick='imgProduto(this);' /></td>

        <td style='text-align:center' title='Apagar Fila' id='apfila2' ><input type='image' src='../../../imagens/apaga/apaga.png' onclick='apProduto(this);' /></td>
    </tr>


        <tr class='alt'>
        <td style='display:none' id='codproduto3' title='codproduto'>80</td>

        <td style='text-align:right' title='Grupo' name='descgrupo' id='descgrupo3' onclick='adlg(this);' >NOVO GRUPO 4</td>

        <td style='text-align:center' title='Marca' name='marca' id='marca3' onclick='adinp(this);'  >MARCA</td>

        <td title='Descrição' name='descproduto' id='descproduto3' onclick='adinp(this);' >PRODUTO3</td>

        <td style='text-align:right' title='Preço sugerido' name='precos' id='precos3' onclick='adinp(this);' >23,40</td>

        <td style='text-align:center' title='Detalhes Produto' id='detfila3' ><input type='image' src='../../../imagens/detalhes/detalhes.png'  onclick='exdetp(this);' /></td>

        <td style='text-align:center' title='Imagem Produto' id='imgfila3' ><input type='image' src='../../../imagens/img.png' onclick='imgProduto(this);' /></td>

        <td style='text-align:center' title='Apagar Fila' id='apfila3' ><input type='image' src='../../../imagens/apaga/apaga.png' onclick='apProduto(this);' /></td>
        </tr>
        </table> 

    The Javascript functions 


        /*ADD THE SELECT BOX OF  GROUPS*/
        function adlg (cell){
      ValueCell = cell.innerHTML;//Value from the cell
      var aPag = 'include/php/produtos/combo/combogrupo.php';
      var fat="&dados="+ValueCell;
      ajax(aPag,fat,false);
      if (oPed.readyState==4 && oPed.status==200){
        document.getElementById(cell.id).innerHTML=oPed.responseText;
        var myInput = document.getElementById("cel");/*Select box of the product groups*/
        myInput.focus();   
        adescuta('keydown','onkeydown',segtp,myInput);/* Adds the listen event */
      }     
        }
        /*ADDS THE LISTEN EVENT TO THE INPUT OR COMBO BOX------*/
        function adescuta(evento1, evento2, keyhand, myInput){
        /*events, function Input*/
      if(myInput.addEventListener )myInput.addEventListener(evento1,keyhand ,true);
      else if(myInput.attachEvent ) myInput.attachEvent(evento2,keyhand); 
    }
        /*------KEY HANDLER FOR PRODUCTS TABLE*/
       function segtp(e) {        
      var TABKEY = 9;   
      var ESCKEY = 27;   
      var ENTERKEY = 13;
      var pad;
      if(e.keyCode == TABKEY || e.keyCode==ENTERKEY) {
        stope(e);//Deter o evento por defeito
        var input= document.getElementById('cel');
        var cel= pegceldoi(input);
        var attonblur=input.getAttribute('onblur');
        var getnode=input.onblur='';
        if(ValueCell!=input.value){      
          err=atbdp(input);//update in database
          if (err!=true){
           alert (err);
           input.focus();
           input.setAttribute('onblur',attonblur);
           return false;
          }else{
            pad=/precos.+/;//
            if (pad.test(cel.id))input.value=number_format(numjs(input.value),2,',','.');
            cel.innerHTML=input.value.toUpperCase();
          }
        }else cel.innerHTML=ValueCell;
        if (e.keyCode== TABKEY){
          cel = percorretabela(cel,'produtos');/*look for valid cel*/
          pad=/descgrupo.+/;
          if(pad.test(cel.id))  adlg(cel);/*Add a select box*/
          else adinp(cel);// /*Add an input box*/
        }
        }
        }
        /*UPDATE */

        function atbdp(input){
          var padsf= new Array(/codproduto.+/,/marca.+/,/descproduto.+/,/descgrupo.+/,/precos.+/);//Padrões da fila
        var dadoscel=input.value;//Data
        var cel=pegceldoi(input);//Cell
        pad=/marca.+/;//Pattern exclude
        if(!pad.test(cel.id)&& vazio(dadoscel)==false) return 'Por favor preencha os dados do registro';//If input not filled
      var aPag = 'include/php/produtos/atualiza/atprodutos.php';
      var produto= pegvf(input,padsf,'produtos');/*patterns of the row*/ fat="&codproduto="+produto[0]+"&marca="+produto[1]+"&descproduto="+produto[2]+"&descgrupo="+produto[3]+"&precos="+numjs(produto[4]);
      ajax(aPag,fat,false);
      if (oPed.readyState==4 && oPed.status==200){
        if(oPed.responseText!='') return oPed.responseText;
        else return true;
      }
    }
    /*---------------AJAX*/
    function ajax(aPag,dados,bool){
      var oRand = parseInt (Math.random()*99999999999999);
      var fNovo="rand="+oRand+dados
      var oURL = aPag;
      oPed=  getXMLHTTPRequest ();
      oPed.open ("POST", oURL, bool);
      oPed.setRequestHeader("Content-type", "application/x-www-form-urlencoded");   // Setando Content-type
      oPed.setRequestHeader("Content-length", fNovo.length);
      oPed.send(fNovo);
    }
    /*ADD INPUT TO THE TABLE */
    function adinp (cell){/*Cell that called the function*/
      var id = cell.id;//Identficador da célula clikada
      ValueCell = cell.innerHTML;/*Value from the cell*/
      var valin="value='"+ValueCell+"'";
      var longInput='', size='';//Tamanho máximo e tamanho do input
      var pad=/marca.+/;//Padrão de ndetificação da célula da marca
      if (pad.test(id)){
        longInput="maxlength='15'";
        size="size='13'";
      }else{
        pad=/descproduto.+/;
        if (pad.test(id)){
          longInput="maxlength='145'";
          size="size='45'";
        }else{
          longInput="maxlength='14'";
          size="size='14'";
          valin="value='"+numsim(ValueCell)+"'";
        }
      }
      cell.innerHTML = "<form name='produtos' style='margin:0; padding:0; padding-left:0; margin-left:0; position:relative'"
      +" onsubmit=' return false;'><input style='margin-left:2px; padding-left:2px' id='cel'"
      +" onblur='atpb(this);'"//Update on blur
      +" onclick='event.cancelBubble=true;'" 
      +" type='text' "
      +valin+" "
      +longInput+" "+size+" /><div class='campoexiste' id='existe'></div></form>";
      document.getElementById('cel').focus();
      var myInput = document.getElementById("cel");  
      adescuta('keydown','onkeydown',segtp,myInput); }
    /*----------------STOP EVENT----------------------------*/
    function stope(e){//Deter o evento por defeito
      if(e.preventDefault)  e.preventDefault();
      else{
        e.stop();
        e.returnValue = false;
        e.stopPropagation();        
      }
    }
    /*--------GET VALUES FROM ROW*/
    function pegvf(input,padsfila,nomtab){//Input, array com os padrões da fila, nome da tabela
      var vfila=new Array;//Valores da fila
      var cel=pegceldoi(input);//Célula que contém o input
      var idfila=cel.parentNode.rowIndex;//Índice da fila da célula
      var x;//Contador do array contador de colunas
        for (x in padsfila){
          if (padsfila[x].test(cel.id))vfila.push(input.value);
          else vfila.push(pegvalcel(padsfila[x],idfila,nomtab));
        }
      return vfila
    }
    ARCHIVO PHP
    Combogrupos.php
    <? 
    /*-----------------SELECT BOX OF----GROUPS*/
    $dados = addslashes(trim(utf8_decode($_POST['dados'])));//Nome do grupo que estava na célula
    $stl="style='margin-left:2px;padding-left:2px'";//Estilo da lista
    $atob="onblur='atpb(this);'";//Função atualiza on blur
    $occb="onclick='event.cancelBubble=true;'";//Cancela eventos bubble do evento click
    $lig="<select id='cel' $stl $atob $occb >";//Lista grupos
    $link=mysql_connect('localhost', '','');
    $db = mysql_select_db("fbinfo",$link);
    $query="SELECT * FROM gruposproduto";
    $res = mysql_query($query,$link);
    echo mysql_error();
    $num=mysql_num_rows($res);
    $sel;//Opção selecionada
    if ($num>0){
      $lig.="<option value='null'>Seleccione um grupo</option>";
      while ($fila = mysql_fetch_array($res, MYSQL_BOTH)){
          if ($fila['descgrupo']==$dados)$sel="selected='selected'";
          else $sel='';
          $lig.="<option $sel value='".$fila['descgrupo']."'>".$fila['descgrupo']."</option>";
      }
    }else{
      $lig.="<option value='null'>Não há grupos</option>";
    }
    $lig.="</select><div id='existe'></div>";
    mysql_close($link);
    echo $lig;
    ?>
    Atprodutos.php
    <? 
    /*-----------UPDATE PRODUCTS*/
    include ('../../util/upper/upper.php');//Função que passa as letras para caixa alta
    foreach ($_POST as &$value)$value=utf8_decode(upper($value));//Decodifica as informações da página 
    $link = mysql_connect('localhost', 'root','fbi02');
    $db = mysql_select_db("fbinfo",$link);
    $query= "SELECT codproduto FROM produtos JOIN gruposproduto AS g ON produtos.idgrupo= g.idgrupo WHERE descproduto='"
    .$_POST['descproduto']."' AND marca='".$_POST['marca']."' AND g.descgrupo='". $_POST['descgrupo']."'";
    $res = mysql_query($query,$link);
    echo mysql_error();
    $num=mysql_num_rows($res);
    if ($num>0){
      $fila=mysql_fetch_array($res);
      if ($fila['codproduto']!=$_POST['codproduto']){
        echo "O produto já existe";
        die;
      }
    }
    $query="UPDATE produtos SET descproduto='".$_POST['descproduto']."' , marca='".$_POST['marca']."' , precos=".$_POST['precos'].", idgrupo=(SELECT idgrupo FROM gruposproduto WHERE descgrupo='".$_POST['descgrupo']."') WHERE codproduto='".$_POST['codproduto']."'";
    $res = mysql_query($query,$link);
    echo mysql_error();
    mysql_close($link);
    ?>

person ricbecen    schedule 16.08.2011    source източник


Отговори (2)


Ако замените HTML елемент чрез AJAX, губите манипулатора на събития. Трябва да инициализирате отново манипулатора на събития след всяко зареждане.

person Diodeus - James MacFarlane    schedule 16.08.2011
comment
Извинете ме, но не разбирам, че улавям събитието и използвам методите e=event e.preventDefault(), e.stop()e.returnValue = false, e.stopPropagation() Това трябва да спре събитието както в IE, така и Firefox, след това използвайте функция за преместване на таблицата и когато бъде намерена следващата валидна клетка, се извиква функцията ajax. Защо обаче, ако тази функция се извика вътре в манипулатор на събития, тя губи обхвата и се прекъсва в firefox? Как може събитието да се инициализира отново, след като е спряно? Веригата от функции е function segtp(e) =› stope(e) =› percorretabela(cel,'produtos')=›adlg(cel)=lose - person ricbecen; 18.08.2011
comment
Как мога да инициализирам повторно манипулатора на събития? - person ricbecen; 23.08.2011
comment
Стартирайте отново същия код, който сте използвали за свързване на манипулатора на събития първия път. - person Diodeus - James MacFarlane; 23.08.2011
comment
Имате предвид да стартирате функцията segtp(event) след XMLHTTP.open? - person ricbecen; 30.08.2011
comment
Разгледайте функционалността .live() на jQuery. Ще помогне. - person Diodeus - James MacFarlane; 30.08.2011
comment
Опитах метода live() по този начин: $(myInput).live(keypress,myfunction); //Не работи - person ricbecen; 30.08.2011
comment
Методът на живо отнема много повече време, причинява произволна позиция в таблицата на IE и в firebug губи реда за отстраняване на грешки след проста клетка.textContent=ABC; тогава ajax работи веднъж и дебъгерът никога повече, докато Firefox не се рестартира - person ricbecen; 06.09.2011

Грешката беше в използването на false за асинхронен метод в AJAX заявката, която получава списъка. Промяната на asyncronous на true и настройката на валидирането и курорта на таблицата извън функцията за манипулиране на събитие реши проблема.

Благодаря ви за цялата помощ, наистина оценявам всички коментари и решения, които ми дадоха много идеи за намиране на решение.

person ricbecen    schedule 04.10.2011