ajax找不到脚本功能

时间:2020-04-09 15:33:19

标签: javascript jquery ajax scope

这是上下文:

  1. 我有一个脚本countrySelect.min.js,该脚本已加载到php页面的页眉中(在其他位置,它不起作用,因此请假定这是正确的脚本)

        <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 )中使用,以将正确的位置应用于某些国家/地区选择下拉框,调用该函数的“ countrySelect ”功能到用 $(“#country_selector” + temp_offer_id)

    标识的对象
    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. 问题:如果用户单击“显示更多”按钮,则在向页面结果中添加新元素时将调用相同的功能。更具体地说,它在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调用的范围内。我觉得这很奇怪;但是,当浏览器调试器停止运行时,我试图查看看到的范围,并且似乎脚本及其功能已经存在,请查看以下屏幕截图:

enter image description here enter image description here

我还没有找到很多类似情况的参考文献(当然不是明确的参考文献),因此确实有帮助的想法。在不太相似的情况下,我阅读了一些有人建议在ajax调用内重新加载脚本的信息。即使我不知道它是否有效,因为我还没有尝试过,我认为既然脚本已经加载到文档中,那么应该在该函数的两个调用中都引用它。这是真的吗?

更新12/04/2020

将应用对象的控制台登录到控制台。countrySelect我可以观察到在工作情况下(下图左侧)有一个链接的countrySelect插件,在不工作的情况下没有

enter image description here

在遵循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>

1 个答案:

答案 0 :(得分:1)

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

中删除countrySelect函数。

让我解释一下

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

enter image description here

enter image description here

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

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

在#4701行

enter image description here

现在,当您在第4701行运行此代码时,发生的情况是country select被附加到先前加载的一个jquery上,并且可以正常工作。然后,将jquery重置,并从jquery context中删除countrySelect,因此,页面完全加载后,您将无法使用countrySelect。

解决方案。

  1. 应该只有一个jquery调用(不是强制性的好习惯,它会减少页面加载时间)

  2. <head>顶部或<body>之前的某个位置加载jquery,然后从#5134行中删除。

在#5134之后加载countrySelect.min.js并将initializeLeafletItems(<?php echo json_encode($offers); ?>);移动到document.ready

在所有jquery加载后执行刚刚加载countrySelect.min.js的操作。

仅供参考:您正在加载的所有jquery的版本均为v3.4.1。因此,我看不出有任何特定原因可将其加载三次。如果我错了请纠正我。

希望对您有帮助。

相关问题