Kod HTML po podmianie poprzez Ajax nie działa.

0

Witam, piszę aplikacje/komponent do systemu Joomla i napotkałem pewien problem związany z Ajax.

Jednym z elementów mojej aplikacji jest generowanie PDF'ów i właśnie przy tym napotkałem na problem. Problem polega na tym, że podmieniam pewien fragment kodu HTML, a konkretnie elementy input type="button" strony poprzez Ajax i właśnie po takiej podmianie przyciski nie reagują na kliknięcia.

Program działa na takiej zasadzie, że na stronie mamy trzy zakładki (page-mail0*), do każdej z zakładek przypisany jest inny plik. Jeżeli klikniemy w jakąś załadkę uruchamiana jest funkcja pdfexists() [plik pdf.json.php], która sprawdza czy istnieje dany plik i w zależnosci od tego wyświetlane są konkretne przyciski. Po kliknięciu w przycisk który tworzy plik PDF (tworzenie pliku obsługuje funkcja createPdf), tworzony jest plik PDF na razie przykładowy, a przyciski poprzez zmienną html wysyłane są przy pomocy json_encode i podmieniane (pdf.js). Analogiczna sytuacja ma miejsce w przypadku pliku usuwania pliku (erasePdf), a także przy sprawdzaniu czy istnieje (pdfexists). Funkcje jQuery uruchamia kliknięcie w elementy o klasie (pdftrigger). Do tworzenie pliku PDF wykorzystuję bibliotekę FPDF.

Problem polega na tym, że jeżeli odświeżę stronę to do pierwszego klinięcia w element z klasą pdftrigger wszystko działa. Jeżli strona zostanie odświeżona to np. jeżeli chcę utworzyć plik PDF to po kliknięciu w przycisk plik się tworzy, jeżeli natomiast chciałbym go skasować to kliknięcie w przycisk już nie działa. Muszę odświeżyć stronę i wtedy mogę kliknąć w przycisk, plik się usuwa, jednak nie mogę go już utworzyć. Muszę ponownie odświeżyć stronę. Mogę natomiast klikać w zakładki, zawsze wyświetla mi się prawidłowa, niezależne od tego ile razy będę klikał w element z data-toggle="tab". Jednak po kliknięciu w niego nawet jeżeli nie klikałem wcześniej w przycisk kliknięcie w przycisk nic nie daje. Zapewnie jest to związane z tym, że równie elementy data-toggle="tab" posiadają klasę pdftrigger.

Poniżej zamieszczam fragmenty kodu. Ajax podobnie jak jQuery jest technologią do której dopiero się wdrażam i nic jeszcze w niej nie tworzyłem, więc proszę o wyrozumiałość.

Mam nadzieje, że wyjaśniłem wszystko w miarę zrozumiale. Pozdrawiam i proszę o pomoc.

PS. W dużym skrócie wygląda to tak, że po podmianie fragmentu kodu html poprzez jQuery, klikanie w podstawione elementy nie jest już wykrywane.

default.php - główny plik. Znajduje się tutaj część kodu która przy pierwszym uruchomieniu strony sprawdza czy plik istnieje, a także zakładki które wyświetlają zawartość w zależności od ich wybrania.

<div class="pdfsection">
<?php if (file_exists($file_name)) : ?>
    <input type="button" rel="downloadPdf" class="btn btn-primary pdftrigger" value="<?php echo JText::_('COM_ZLECENIA_DOWNLOAD_PDF'); ?>">
    <input type="button" rel="erasePdf" class="btn btn-danger pdftrigger" value="<?php echo JText::_('COM_ZLECENIA_ERASE_PDF'); ?>">
<?php else : ?>
    <input type="button" rel="createPdf" class="btn btn-primary pdftrigger" value="<?php echo JText::_('COM_ZLECENIA_GENERATE_PDF'); ?>">
<?php endif; ?>
</div>

<input type="hidden" name="order_id" value="<?php echo $order->order->order_id; ?>" />

<ul class="nav nav-tabs">
    <li class="active" >
        <a href="#page-mail01" class="pdftrigger mail01" rel="pdfexists" data-toggle="tab"><?php echo JText::_('COM_ZLECENIA_ORDERS_MAIL_OFFER_TAB_TITLE'); ?></a>
    </li>
    <li>
        <a href="#page-mail02" class="pdftrigger mail02" rel="pdfexists" data-toggle="tab"><?php echo JText::_('COM_ZLECENIA_ORDERS_MAIL_OFFER_SHORT_TAB_TITLE'); ?></a>
    </li>
    <li>
        <a href="#page-mail03" class="pdftrigger mail03" rel="pdfexists" data-toggle="tab"><?php echo JText::_('COM_ZLECENIA_ORDERS_MAIL_ORDER_TAB_TITLE'); ?></a>
    </li>
</ul>
<div class="tab-content">
    <div id="page-mail01" class="tab-pane active">
        <?php echo $mail['mailOffer']; ?>
    </div>
    <div id="page-mail02" class="tab-pane">
        <?php echo $mail['mailOfferShort']; ?>
    </div>
    <div id="page-mail03" class="tab-pane">
        <?php echo $mail['mailOrder']; ?>
    </div>
</div>

pdf.js - plik z kodem javascript/jquery obsługujący te kliknięcia

(function($){

    $(document).ready(function(){
        
        $(".pdftrigger").click(function(){

            alert('test');

            var $this = $(this);
            var action = $this.attr('rel');
            var order_id = document.getElementsByName("order_id")[0].value;

            if (action == 'pdfexists') {
                var active = $this.attr('class')[16];
            } else {
                /* Wybranie aktywnej karty i obliczenie typu wiadomości */
                var Tabs = document.getElementsByClassName("nav-tabs")[0].getElementsByTagName("LI");
        
                var active = 0;
        
                for (index = 0; index < Tabs.length; index++) {
                    if (Tabs[index].className == "active") {
                        active = index + 1;
                    }
                }
            }

            $.post(
                'index.php',
                {
                    option: 'com_zlecenia',
                    task: 'pdf.'+action,
                    format: 'json',
                    type: active,
                    order_id: order_id,
                    tmpl: 'raw'
                },
                function(respJSON) {
                    document.getElementsByClassName('pdfsection')[0].innerHTML = respJSON.html;
                    console.log(respJSON);
                },
                'json'
            );

            if (action == 'pdfexists') {
                return true;
            } else {
                return false;
            }

        });

    });

})(jQuery)

pdf.json.php - plik zawierający funkcje, które wywołuje jQuery

<?php
defined('_JEXEC') or die;

jimport('joomla.application.component.controller');

class ZleceniaControllerPdf extends JControllerLegacy {

    function createPdf() {

        require_once(JPATH_COMPONENT . '/helpers/fpdf.php');
        $index = $this->getModel('Order')->getIndex(JRequest::getInt('order_id'))->order_index;
        $file_name = strtolower('images/orders/'.str_replace('/','',$index).JRequest::getInt('type').'.pdf');

        $pdf = new FPDF();
        $pdf->AddPage();
        $pdf->SetFont('Arial','B',16);
        $pdf->Cell(40,10,'Hello World!');
        $pdf->Output('F', $file_name);
        
        $html = '<input type="button" rel="downloadPdf" class="btn btn-primary pdftrigger" value="'.JText::_('COM_ZLECENIA_DOWNLOAD_PDF').'"> ';
        $html .= '<input type="button" rel="erasePdf" class="btn btn-danger pdftrigger" value="'.JText::_('COM_ZLECENIA_ERASE_PDF').'">';

        echo json_encode(array(
            'status' => 'OK',
            'file_name' => $file_name,
            'object' => JRequest::get(),
            'html' => $html
        ));
        
        return TRUE;

    }

    function erasePdf() {

        $index = $this->getModel('Order')->getIndex(JRequest::getInt('order_id'))->order_index;
        $file_name = strtolower('images/orders/'.str_replace('/','',$index).JRequest::getInt('type').'.pdf');

        unlink($file_name);

        $html = '<input type="button" rel="createPdf" class="btn btn-primary pdftrigger" value="'.JText::_('COM_ZLECENIA_GENERATE_PDF').'">';

        echo json_encode(array(
            'html' => $html
        ));

        return TRUE;

    }

    function pdfexists() {

        //pobranie numeru aktualnego zlecenia
        $index = $this->getModel('Order')->getIndex(JRequest::getInt('order_id'))->order_index;
        $file_name = strtolower('images/orders/'.str_replace('/','',$index).JRequest::getInt('type').'.pdf');

        if (file_exists($file_name)) {
            $html = '<input type="button" rel="downloadPdf" class="btn btn-primary pdftrigger" value="'.JText::_('COM_ZLECENIA_DOWNLOAD_PDF').'"> ';
            $html .= '<input type="button" rel="erasePdf" class="btn btn-danger pdftrigger" value="'.JText::_('COM_ZLECENIA_ERASE_PDF').'">';
        } else {
            $html = '<input type="button" rel="createPdf" class="btn btn-primary pdftrigger" value="'.JText::_('COM_ZLECENIA_GENERATE_PDF').'">';
        }

        echo json_encode(array(
            'order_id' => $index,
            'active' => JRequest::getInt('type'),
            'html' => $html
        ));

        return TRUE;

    }

}
1

No nic dziwnego, że nie działają skoro za każdym żądaniem podmieniasz całą zawartość <div class="pdfsection">. W tym przyciski, które się tam znajdowały. Wsadzasz tam nowe przyciski, ale to już nie są te same, tylko całkowicie nowe elementy DOM. Wszystkie eventy muszą zostać do nich ponownie podpięte. Czyli całe to:

$(".pdftrigger").click(function(){ ... });

Za każdym razem musi być podpinane od nowa.

Ewentualnie możesz dodać nasłuchiwanie kliknięć na jakimś rodzicu, np. na tym <div class="pdfsection">. A potem wykrywać, który element wewnątrz jego został kliknięty.

0

Dzięki. Teraz już działa. Zrobiłem tak jak sugerowałeś, poprzez nasłuchiwanie na rodzicu.

1 użytkowników online, w tym zalogowanych: 0, gości: 1