ajax 没有找到脚本函数

ajax does not find a script function

这是上下文:

  1. 我有一个脚本,countrySelect.min.js,它被加载到 php 页面的 header 中(在其他位置它不起作用,所以假设这是正确的)

        <script src="<?php echo base_url(); ?>assets/owlcarousel/owl.carousel.js"></script>
    
        <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/bootstrap.min.js"></script>
    
        <script type="text/javascript" src="<?php echo base_url('assets/js/commonFunctions.js'); ?>"></script>
    
        <link rel="stylesheet" href="<?php echo base_url('assets/css/countrySelect.css'); ?>">  
    
        <script type="text/javascript" src="<?php echo base_url('assets/js/countrySelect.min.js'); ?>"></script>
    
        <link rel="stylesheet" href="<?php echo base_url('assets/css/countrySelectorStyle.css'); ?>">   
    
  2. 此脚本在函数 (initializeLeafletItems) 内使用,以在正确位置应用某些国家/地区选择 drop-down 框调用其函数“countrySelect" 应用到用 $("#country_selector"+temp_offer_id)[ 标识的 objects =22=]

    function initializeLeafletItems(offers){
    
        leaflets_info = {};
        var temp_product_info_id;
        var temp_product_info = {};
        var temp_offer_id;
        var temp_default_country_code;
    
        const observer = new MutationObserver(function(mutationsList, observer) {
          [...]
        )};
    
        [...]
    
        for(var index in offers){
    
            if(offers[index]['package_leaflets']){
    
                temp_default_country_code = offers[index]['defaultCountry'];
                temp_offer_id = offers[index]['id'];
    
                $("#country_selector"+temp_offer_id).countrySelect({
                    defaultCountry: temp_default_country_code,
                    onlyCountries: offers[index]['countries_list'],
                    responsiveDropdown: true,
                });
    
                [...]
            } 
         }
    
  3. 这个函数几乎在文档末尾被调用,但在 $(document).ready(function) 语句之外。它工作正常,没有任何错误。

    initializeLeafletItems(<?php echo json_encode($offers); ?>); 
    
  4. 问题:如果用户单击 "SHOW MORE" 按钮,将新元素添加到页面结果时会调用相同的函数。更具体地说,它在 ajax 语句

    中被调用
    function show_offers(render, from_item, to_item, products_id_list, searchedGeneric, searchedMade, searchedCountries, searchedFormats, searchedCurrency, keywords_id){
    
        if (render == 'PCRender') {
    
            $.ajax({
                method:'POST',
                url: ajax_url+'frontController/addRenderScreenOffers',
                data:{  
                              [...]
                },
                dataType:'json',
    
                success:function(res)
                { 
    
                    if(res['rendered_PC_screen_offers'] != 'empty'){
    
                        $("#offers-product tbody").append(res['rendered_PC_screen_offers']);
                        from_item = to_item + 1;
                        to_item = to_item + 10;
                        $("#show_more_button").replaceWith('[...] )">Show More</button>');
    
                        initializeLeafletItems(res['offers']['offers']);
    

在这种情况下,我得到这个错误

        Uncaught TypeError: $(...).countrySelect is not a function

好像该函数不在 show_offers 函数或 ajax 调用的同一范围内。我觉得这很奇怪;然而,当浏览器调试器停止时,我试图查看所看到的范围,似乎脚本及其功能已经存在,请查看这些屏幕截图:

我没有找到很多关于类似案例的参考资料,当然不是明确的参考资料,所以对它有想法真的很有帮助。我四处阅读,在不太相似的情况下,有人建议 re-load ajax 调用中的脚本。即使我不知道它是否有效(因为我还没有尝试过),我认为由于脚本已经加载到文档中,所以应该有一种方法可以在该函数的两个调用中引用它。这是真的吗?

2020 年 4 月 12 日更新

登录到控制台 object 它应用了 .countrySelect 我可以观察到在工作情况下(下图中左侧)有一个链接的 countrySelect 插件,在不工作的情况下不是

根据 countrySelect 作者 Mark 的建议,我在一个更简单的页面上重复了测试,我发现它在本地(单击按钮时添加一个元素)和 ajax 调用都有效。这里遵循控制器和查看器的代码;所以我也尝试在不工作的页面上添加简单的测试,通过单击一个没有任何 ajax 的按钮来添加输入元素。即使在这种情况下,它也不起作用(但它仍然适用于同一页面的第一次下载中的元素)。任何的想法?似乎在该页面上丢失了某些内容或交互不良。

这里是简单页面上的工作代码(https://www.pharmacomparison.com/frontController/countrySelectTest/)

控制器:

 function countrySelectTest(){

    $this->load->view('countrySelectTest');

}

function countrySelectTestresult(){

    $random = mt_rand(0,999999999);
    $res['html_text']  = '<input type="text" id="country_selector_ajax'.$random.'" name="country_selector_ajax">';
    $res['state']  = 'success';
    $res['random'] = $random;

    echo json_encode($res);
}

观众

        <head>
        <meta charset="utf-8">
        <title>Country Select JS</title>
        <link rel="stylesheet" href="build/css/countrySelect.css">
        <link rel="stylesheet" href="build/css/demo.css">

                <link rel="stylesheet" href="<?php echo base_url('assets/css/countrySelect.css'); ?>">    
                <link rel="stylesheet" href="<?php echo base_url('assets/css/demo.css'); ?>">  

                <script type="text/javascript" src="<?php echo base_url(); ?>assets/js/jquery.js"></script>
                <script type="text/javascript" src="<?php echo base_url('assets/js/countrySelect.min.js'); ?>"></script>

        </head>
        <body>
        <h1>Country Select JS</h1>
        <form>
        <div class="" id="country">
        <input id="country" type="text">
        <label for="country_selector" style="display:none;">Select a country here...</label>
        </div>

        <button type="submit" style="display:none;">Submit</button>
        </form>
                    <button type="submit"  id="local_test">Local Test</button>
                    <button type="submit"  id="ajax_test">Ajax Test</button>
        <!-- Load jQuery from CDN so can run demo immediately -->

        <script>

        $("#country").countrySelect({
        // defaultCountry: "jp",
        // onlyCountries: ['us', 'gb', 'ch', 'ca', 'do'],
        // responsiveDropdown: true,
        preferredCountries: ['ca', 'gb', 'us']
        });


        </script>

        <script>
        // Make sure we don't run this until after everything else has been loaded.
        // Using the document click handler ensures that everything else is setup first,
        // which ensures we're not cheating and adding our new element before the
        // plugin attaches to form elements the first time.

        $('#local_test').on('click', function(){

        // Step 1: Create a new element from a simulated AJAX request    
        var newInput = $('<input type="text" id="country_selector_local" name="country_selector_local">');

        // Step 2: Add the new element to the page
        $('form').append(newInput);

        // Step 3: Run the plugin on the new element
        $('#country_selector_local').countrySelect({ defaultCountry: 'au' });

        // Step 4: Profit!
        });

        $('#ajax_test').on('click', function(){

                    //the URL return te same content of previous newInput
                    $.ajax({                                                                  

                        url: 'https://www.pharmacomparison.com/frontController/countrySelectTestResult/',  
                        type: "POST",                                                          
                        enctype: 'multipart/form-data',                                      
                        data: {                                                            
                            product_info_id: 'test'                                                                  
                        },  
                        method: 'Post',  
                        dataType: 'json',  

                        success: function(response) {  
                            if(response.state=='error'){                  

                                alert(response.msg);  
                            }                        

                            if(response.state=='success'){  

                                // Step 2: Add the new element to the page
                                $('form').append(response.html_text);

                                // Step 3: Run the plugin on the new element
                                $('#country_selector_ajax'+response['random']).countrySelect({ defaultCountry: 'au' });

                                // Step 4: Profit!  

                            }

                        },



                        error: function(xhr, status, error) {      
        console.log(xhr);
        console.log(status);
        console.log(error);
                            alert("The request returned an error, please alert the site administrators (" + status +").");

                        }    
                    });      
               });


        </script>


        </body>

问题是您在 initializeLeafletItems(<?php echo json_encode($offers); ?>); 调用结束后重新初始化 jquery。这是重置 jquery 上下文并从 $.fn

中删除 countrySelect 函数

让我解释一下

  1. 请注意,您在同一文档中 jquery 不是两次而是三次初始化。

看到它们在第 56、58 和 5134 行。

  1. 现在您正在呼叫
initializeLeafletItems(<?php echo json_encode($offers); ?>); 

在线#4701

现在,当您 运行 将第 4701 行国家 select 上的此代码附加到先前加载的 jquery 之一并且它起作用时,会发生什么。然后重置 jquery 并从 jquery context 中删除 countrySelect 因此,一旦页面完全加载,您将无法使用 countrySelect。

解决方案。

  1. 应该只有一个 jquery 调用(不是强制性的,只是一种好的做法,它会降低您的页面加载时间)

  2. <head> 顶部或 <body> 之前的某处加载 jquery 并从行 #5134 中删除。

在#5134 之后加载 countrySelect.min.js 并在 document.ready

中移动 initializeLeafletItems(<?php echo json_encode($offers); ?>);

在加载完所有 jquery 后,只加载 countrySelect.min.js。

仅供参考:您正在加载的所有 jquery 都是相同的 v3.4.1 版本。所以我没有看到任何特定的理由来三次加载它。如果我错了请纠正我。

希望对你有帮助。