Uncaught TypeError: Невозможно установить свойство FUNCTION_NAME из undefined для реализации виджета.

Я пытаюсь разработать виджет jQuery, который можно встроить на любой сайт. Ниже приведен код сценария:

(function($) {
    var jQuery;
    if (window.jQuery === undefined || window.jQuery.fn.jquery !== '1.6.2')
    {
        var script_tag = document.createElement('script');
        script_tag.setAttribute("type","text/javascript");
        script_tag.setAttribute("src","http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js");
        script_tag.onload = scriptLoadHandler;
        script_tag.onreadystatechange = function () 
        { 
            if (this.readyState == 'complete' || this.readyState == 'loaded')
                scriptLoadHandler();
        };
        (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);
    }
    else 
    {
        jQuery = window.jQuery;
        main();
    }
    function scriptLoadHandler() 
    {
        jQuery = window.jQuery.noConflict(true);
        main();
    }
    function main() {
        jQuery(document).ready(function($) {
            var css = $("<link>", { rel: "stylesheet", type: "text/css", href: "http://mysite.com/my_css_path.css" });
            css.appendTo('head');
        });
        $.fn.fetchfeed = function(options) {
            var defaults = {
                //default params;
            };
            var opts = $.extend(defaults, options);

            var myURL = "http://mysite.com/"+opts.user+".json?";
            var params = "&callback=?"
            var jsonp_url = myURL + encodeURIComponent(params);

            $.getJSON(jsonp_url, function(data) {
                //build widget html
            })
            .error(function() {
                //show error
            });
        }
    }
})(jQuery);

А вот код, который необходимо разместить на сайте Пользователя:

 <script id='mywidgetscript' src='http://my_site.com/javascripts/widget.js'></script>
 <div id='my-widget-container'></div>
 <script>$('#my-widget-container').fetchfeed({/*parameters*/});</script>

Когда я помещаю этот код на другой сайт и пытаюсь загрузить виджет, он выдает ошибку Uncaught TypeError: Can not set property 'fetchfeed' of undefined и не может загрузить виджет. Что могло быть не так?

Удивительно, но этот код виджета работает на моем сайте на localhost !!!


person Bongs    schedule 19.10.2011    source источник


Ответы (2)


Если jQuery не был определен до выполнения вашего кода, вы получите TypeError здесь:

$.fn.fetchfeed

потому что $ не являются объектом jQuery. Попробуйте переместить эту строку и следующий код в main() в конструкцию jQuery(document).ready(function($){ ... }); выше.

person Phillip Kovalev    schedule 19.10.2011
comment
Я уже пробовал это. Та же ошибка ... Но почему этот код работает правильно на моем сайте localhost, а не когда я пытаюсь встроить в blogger ??? Он передает нулевой / неопределенный элемент ?? - person Bongs; 19.10.2011

Хорошо, после бесчисленных попыток я решил это и многому научился. Тем не менее, я не понимаю многих вещей. Исправьте меня, отредактировав этот ответ, или прокомментируйте, если найдете что-то не так.

Первый $.fn был пустым (или ему было передано значение null / undefined). Причина, сценарий запускался после вызова <script>$('#my-widget-container').fetchfeed({/*parameters*/});</script>. Итак, .fetchfeed({...}) не был определен.

Затем я переместил код в window.onload, он дал мне ошибку can not call method fetchfeed on null. Это должно быть потому, что он не получал элемент (т.е. $('#my-widget-container')), также скрипт не смог распознать $.

Опять же, после нескольких настроек изменение $.fn.fetchfeed в function fetchfeed() {...} дало мне ошибку undefined fetchfeed. Это произошло потому, что функция fetchfeed находилась внутри другой функции.

Также кодировка параметра &callback=? дает ошибку Access-Control-Allow-Origin. Это должно быть передано в URL как есть.

После некоторого исследования я изменил код, как показано ниже, и теперь работает правильно.

function fetchfeed(options) {
    var o = options;
    var jQuery;
    if (window.jQuery === undefined || window.jQuery.fn.jquery !== '1.6.2')
    {
        var script_tag = document.createElement('script');
        script_tag.setAttribute("type","text/javascript");
        script_tag.setAttribute("src","http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js");
        script_tag.onload = scriptLoadHandler;
        script_tag.onreadystatechange = function () 
        { 
            if (this.readyState == 'complete' || this.readyState == 'loaded')
                scriptLoadHandler();
        };
        (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);
    }
    else 
    {
        jQuery = window.jQuery;
        ff(jQuery, o);
    }
    function scriptLoadHandler() 
    {
        jQuery = window.jQuery.noConflict(true);
        ff(jQuery, o);
    }
    function ff($, options) {
        var defaults = {
            ...
        };
        var opts = $.extend(defaults, options);

        var jsonp_url = "http://mysite.com/?callback=?";            
        $.getJSON(jsonp_url, function(data) {
            //success
        })
        .error(function() {
            //fail
        });
    }
}

Код на сайте / блоге пользователя будет

<div id='my-widget-container'></div>
<script id='my_widget_script' src='https://PATH_OF_SCRIPT/FILE_NAME.js'></script>
<script type='text/javascript'>
    fetchfeed({/*params*/});
</script>

Функция будет выполнена после завершения загрузки страницы.

person Bongs    schedule 22.10.2011