jQuery 和 .data()

发布于 2024-11-03 18:42:06 字数 6443 浏览 2 评论 0原文

我正在编写一个 jQuery 插件,我需要通过我的插件方法调用来保留对象。所以我尝试按照此处的建议使用 .data()http:// docs.jquery.com/Plugins/Authoring

但我无法检索我存储的对象,这里是我的代码:

(function($) {
    var methods = {
        init : function(options) {
            return this.each(function() {
                var $this = $(this);
                var geocoder = new google.maps.Geocoder();
                var settings = {
                    'geocodeSearch': {address: 'France'}
                };

                // Merge default settings with user ones
                if (options) {
                    $.extend(settings, options);
                }

                function drawMap(geocodeResult) {
                    var mapSettings = {
                        center: geocodeResult[0].geometry.location,
                        mapTypeControl: true,
                        mapTypeId: google.maps.MapTypeId.SATELLITE,
                        overviewMapControl: false,
                        panControl: true,
                        scaleControl: true,
                        streetViewControl: false,
                        zoom: 6,
                        zoomControl: true,
                        zoomControlOptions: { style: google.maps.ZoomControlStyle.SMALL }
                    };

                    var element = document.getElementById($this.attr("id"));
                    var map = new google.maps.Map(element, mapSettings);
                    var cluster = new MarkerClusterer(map);

                    cluster.setGridSize(100);

                    $this.data('eventsmap', {
                        cluster: cluster,
                        map: map
                    });
                }

                    geocoder.geocode(settings.geocodeSearch, drawMap);
            });
        },
        restrictZoom : function(minimalZoom, maximalZoom) {
            return this.each(function() {
                var $this = $(this);
                console.log($this.data());
                console.log($this.data('eventsmap'));

                //google.maps.event.addListener(map, 'zoom_changed', function() {
                //  if (map.getZoom() > maximalZoom) {
                //      map.setZoom(maximalZoom);
                //  }
                //  if (map.getZoom() < minimalZoom) {
                //      map.setZoom(minimalZoom);
                //  }
                //});
                //cluster.setMaxZoom(maximalZoom-1);
            });
        }
    };

    $.fn.eventsMap = function(method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === 'object' || !method) {
            return methods.init.apply(this, arguments);
        } else {
            $.error( 'Method ' +  method + ' does not exist on jQuery.eventsMap' );
        }
    };
})(jQuery);

当我调用restrictZoom方法时,$this.data()(第48行)从DOM返回数据,但是如果我尝试获取在 init 方法期间设置的“eventsmap”属性,则会出现未定义的情况($this.data('eventsmap') 第 49 行)。 我确信这是正确的 DOM 对象,而我的对象是正确的,因为我可以通过浏览器调试器看到它​​们:

Chrome output

I不知道该怎么办。

编辑:html:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-us" xml:lang="en-us" > 
<head> 
<title>Map tool | Django site admin</title> 
<link rel="stylesheet" type="text/css" href="/static/admin/css/base.css" /> 

<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/themes/ui-darkness/jquery-ui.css" /> 

<!--[if lte IE 7]><link rel="stylesheet" type="text/css" href="/static/admin/css/ie.css" /><![endif]--> 

<script type="text/javascript">window.__admin_media_prefix__ = "/static/admin/";</script> 

<script type="text/javascript" src="https://maps.google.com/maps/api/js?sensor=false"></script> 
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script> 
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.js"></script> 
<script type="text/javascript" src="/static/earthquake/js/markerclusterer.js"></script> 
<script type="text/javascript" src="/static/earthquake/js/map.js"></script> 

<meta name="robots" content="NONE,NOARCHIVE" /> 
</head> 


<body class="eventsmap"> 

<!-- Container --> 
<div id="container"> 


    <!-- Header --> 
    <div id="header"> 
        <div id="branding"> 
        <h1 id="site-name">Events database</h1> 
        </div> 

        <div id="user-tools"> 
            Welcome,
            <strong>admin</strong>.



                    <a href="/admin/doc/">Documentation</a> /



                    <a href="/admin/password_change/"> 

                Change password</a> /


                    <a href="/admin/logout/"> 

                Log out</a> 

        </div> 


    </div> 
    <!-- END Header --> 

<div class="breadcrumbs"> 
<a href="/admin/">Home</a> &rsaquo; <a href="/admin/events">Events</a> &rsaquo; Map tool
</div> 





    <!-- Content --> 
    <div id="content" class="colM"> 



<div id="eventsmap" style="width: 100%;"></div> 
<script> 
$(document).ready(function() {
    var mapCanvas = $("#eventsmap");

    // Cleanup and prepare HTML from Django
    $("#footer").remove();
    $("html").height("100%");
    $("body").height("100%");
    $("body").css("overflow-y", "hidden");
    $("#content").css('margin', 0);
        mapCanvas.height($(document).height()-57);

    mapCanvas.eventsMap({
        geocodeSearch: {address: 'France'}
    });
    mapCanvas.eventsMap('restrictZoom', {
        minimalZoom: 2,
        maximalZoom: 9
    });
});
</script> 


        <br class="clear" /> 
    </div> 
    <!-- END Content --> 

    <div id="footer"></div> 
</div> 
<!-- END Container --> 

</body> 
</html> 

I'm writing a jQuery plugin and I need to keep objects through my plugin method calls. So I tried to use .data() as recommended here : http://docs.jquery.com/Plugins/Authoring

but I'm unable to retrieve my stored objects, here my code :

(function($) {
    var methods = {
        init : function(options) {
            return this.each(function() {
                var $this = $(this);
                var geocoder = new google.maps.Geocoder();
                var settings = {
                    'geocodeSearch': {address: 'France'}
                };

                // Merge default settings with user ones
                if (options) {
                    $.extend(settings, options);
                }

                function drawMap(geocodeResult) {
                    var mapSettings = {
                        center: geocodeResult[0].geometry.location,
                        mapTypeControl: true,
                        mapTypeId: google.maps.MapTypeId.SATELLITE,
                        overviewMapControl: false,
                        panControl: true,
                        scaleControl: true,
                        streetViewControl: false,
                        zoom: 6,
                        zoomControl: true,
                        zoomControlOptions: { style: google.maps.ZoomControlStyle.SMALL }
                    };

                    var element = document.getElementById($this.attr("id"));
                    var map = new google.maps.Map(element, mapSettings);
                    var cluster = new MarkerClusterer(map);

                    cluster.setGridSize(100);

                    $this.data('eventsmap', {
                        cluster: cluster,
                        map: map
                    });
                }

                    geocoder.geocode(settings.geocodeSearch, drawMap);
            });
        },
        restrictZoom : function(minimalZoom, maximalZoom) {
            return this.each(function() {
                var $this = $(this);
                console.log($this.data());
                console.log($this.data('eventsmap'));

                //google.maps.event.addListener(map, 'zoom_changed', function() {
                //  if (map.getZoom() > maximalZoom) {
                //      map.setZoom(maximalZoom);
                //  }
                //  if (map.getZoom() < minimalZoom) {
                //      map.setZoom(minimalZoom);
                //  }
                //});
                //cluster.setMaxZoom(maximalZoom-1);
            });
        }
    };

    $.fn.eventsMap = function(method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === 'object' || !method) {
            return methods.init.apply(this, arguments);
        } else {
            $.error( 'Method ' +  method + ' does not exist on jQuery.eventsMap' );
        }
    };
})(jQuery);

When I call restrictZoom method, $this.data() (line 48) returns data from the DOM but if I try to get the 'eventsmap' attribute as set during the init method, I got undefined ($this.data('eventsmap') line 49).
I'm sure it's the right DOM object and my objects are because I can see them trhough my browser debugger :

Chrome output

I dunno what to do.

Edited : html :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-us" xml:lang="en-us" > 
<head> 
<title>Map tool | Django site admin</title> 
<link rel="stylesheet" type="text/css" href="/static/admin/css/base.css" /> 

<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/themes/ui-darkness/jquery-ui.css" /> 

<!--[if lte IE 7]><link rel="stylesheet" type="text/css" href="/static/admin/css/ie.css" /><![endif]--> 

<script type="text/javascript">window.__admin_media_prefix__ = "/static/admin/";</script> 

<script type="text/javascript" src="https://maps.google.com/maps/api/js?sensor=false"></script> 
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script> 
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.js"></script> 
<script type="text/javascript" src="/static/earthquake/js/markerclusterer.js"></script> 
<script type="text/javascript" src="/static/earthquake/js/map.js"></script> 

<meta name="robots" content="NONE,NOARCHIVE" /> 
</head> 


<body class="eventsmap"> 

<!-- Container --> 
<div id="container"> 


    <!-- Header --> 
    <div id="header"> 
        <div id="branding"> 
        <h1 id="site-name">Events database</h1> 
        </div> 

        <div id="user-tools"> 
            Welcome,
            <strong>admin</strong>.



                    <a href="/admin/doc/">Documentation</a> /



                    <a href="/admin/password_change/"> 

                Change password</a> /


                    <a href="/admin/logout/"> 

                Log out</a> 

        </div> 


    </div> 
    <!-- END Header --> 

<div class="breadcrumbs"> 
<a href="/admin/">Home</a> › <a href="/admin/events">Events</a> › Map tool
</div> 





    <!-- Content --> 
    <div id="content" class="colM"> 



<div id="eventsmap" style="width: 100%;"></div> 
<script> 
$(document).ready(function() {
    var mapCanvas = $("#eventsmap");

    // Cleanup and prepare HTML from Django
    $("#footer").remove();
    $("html").height("100%");
    $("body").height("100%");
    $("body").css("overflow-y", "hidden");
    $("#content").css('margin', 0);
        mapCanvas.height($(document).height()-57);

    mapCanvas.eventsMap({
        geocodeSearch: {address: 'France'}
    });
    mapCanvas.eventsMap('restrictZoom', {
        minimalZoom: 2,
        maximalZoom: 9
    });
});
</script> 


        <br class="clear" /> 
    </div> 
    <!-- END Content --> 

    <div id="footer"></div> 
</div> 
<!-- END Container --> 

</body> 
</html> 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风和你 2024-11-10 18:42:06

总的来说,代码看起来非常好。但这里有两个想法:

  1. 您是否尝试过在该数据函数中存储更简单的对象文字,以确保代码可以正常工作?您当前正在存储一个 Google Map 对象和一个 MarkerCluster。这些对象是否太复杂而无法编码为 json 并存储在数据属性中? (不记得它们是否只是对象文字,或者它们是否也包含函数和其他元素)

  2. 只是一种风格,但有许多重用的名称使得调试代码变得更加困难。 (总的来说,你的代码很棒)有两个名为 $this 的不同变量(看起来像是在不同的范围内)和三个名为 eventsmap 的项目(一个 css 类、一个 js 变量和一个扩展函数)。虽然它们可能没问题,但可能会让一些阅读此代码的人感到困惑。

我希望这能激发一些想法!

Overall the code looks really good. But here are two ideas:

  1. Have you tried to store a simpler object literal in that data function to ensure that to code works otherwise? You're currently storing a Google Map object and a MarkerCluster. Are those objects too complex to encode to json and store in a data attribute? (Can't remember if they are simply object literals or if they have functions and other elements in them as well)

  2. Just a stylistic thing, but there are a number of reused names that make it harder to debug the code. (overall your code is great) There are two different variables named $this (in different scopes it looks like) and three items named eventsmap (a css class, a js variable and an extension function). While they're probably fine, it may trip up some folks reading over this code.

I hope that sparks some ideas!

鱼忆七猫命九 2024-11-10 18:42:06

我终于弄清楚为什么它不起作用,我必须确保插件方法是同步调用的。为了实现这一点,我将我的方法包装在 jQuery .queue 函数中,如下所示:

(function($) {
var methods = {
    init : function(options) {
        return this.each(function() {
            $(this).queue(function() {
                var $this = $(this), data = $this.data('eventsmap');
                var geocoder = new google.maps.Geocoder();
                var settings = {
                    'geocodeSearch': {address: 'France'}
                };

                // Merge default settings with user ones
                if (options) {
                    $.extend(settings, options);
                }

                function drawMap(geocodeResult) {
                    var mapSettings = {
                        center: geocodeResult[0].geometry.location,
                        mapTypeControl: true,
                        mapTypeId: google.maps.MapTypeId.SATELLITE,
                        overviewMapControl: false,
                        panControl: true,
                        scaleControl: true,
                        streetViewControl: false,
                        zoom: 6,
                        zoomControl: true,
                        zoomControlOptions: { style: google.maps.ZoomControlStyle.SMALL }
                    };

                    var element = document.getElementById($this.attr("id"));
                    var map = new google.maps.Map(element, mapSettings);
                    var cluster = new MarkerClusterer(map);

                    cluster.setGridSize(100);

                    if (!data) {
                        $this.data('eventsmap', {
                            cluster: cluster,
                            map: map
                        });
                    }
                    $this.dequeue();
                }

                geocoder.geocode(settings.geocodeSearch, drawMap);
            })
        });
    },
    restrictZoom : function(args) {
        var minimalZoom = args.minimalZoom;
        var maximalZoom = args.maximalZoom;

        return this.each(function() {
            $(this).queue(function() {
                var $this = $(this), data = $this.data('eventsmap');

                google.maps.event.addListener(data.map, 'zoom_changed', function() {
                    if (data.map.getZoom() > maximalZoom) {
                        data.map.setZoom(maximalZoom);
                    }
                    if (data.map.getZoom() < minimalZoom) {
                        data.map.setZoom(minimalZoom);
                    }
                });

                data.cluster.setMaxZoom(args.maximalZoom-1);

                $(this).dequeue();
            });
        });
    }
};

$.fn.eventsMap = function(method) {
    if (methods[method]) {
        return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
    } else if (typeof method === 'object' || !method) {
        return methods.init.apply(this, arguments);
    } else {
        $.error( 'Method ' +  method + ' does not exist on jQuery.eventsMap' );
    }
};
})(jQuery);

现在它的工作方式就像一个魅力,我在 init 方法中设置它之前调用 myObject.data('eventsmap') 顺便说一句,我仍然无法解释为什么我可以在浏览器中看到该对象...:)

I finally figured out why it didn't work, I had to ensure that plugin methods are synchronous called. To realize this, I wrap my methods in jQuery .queue function like this :

(function($) {
var methods = {
    init : function(options) {
        return this.each(function() {
            $(this).queue(function() {
                var $this = $(this), data = $this.data('eventsmap');
                var geocoder = new google.maps.Geocoder();
                var settings = {
                    'geocodeSearch': {address: 'France'}
                };

                // Merge default settings with user ones
                if (options) {
                    $.extend(settings, options);
                }

                function drawMap(geocodeResult) {
                    var mapSettings = {
                        center: geocodeResult[0].geometry.location,
                        mapTypeControl: true,
                        mapTypeId: google.maps.MapTypeId.SATELLITE,
                        overviewMapControl: false,
                        panControl: true,
                        scaleControl: true,
                        streetViewControl: false,
                        zoom: 6,
                        zoomControl: true,
                        zoomControlOptions: { style: google.maps.ZoomControlStyle.SMALL }
                    };

                    var element = document.getElementById($this.attr("id"));
                    var map = new google.maps.Map(element, mapSettings);
                    var cluster = new MarkerClusterer(map);

                    cluster.setGridSize(100);

                    if (!data) {
                        $this.data('eventsmap', {
                            cluster: cluster,
                            map: map
                        });
                    }
                    $this.dequeue();
                }

                geocoder.geocode(settings.geocodeSearch, drawMap);
            })
        });
    },
    restrictZoom : function(args) {
        var minimalZoom = args.minimalZoom;
        var maximalZoom = args.maximalZoom;

        return this.each(function() {
            $(this).queue(function() {
                var $this = $(this), data = $this.data('eventsmap');

                google.maps.event.addListener(data.map, 'zoom_changed', function() {
                    if (data.map.getZoom() > maximalZoom) {
                        data.map.setZoom(maximalZoom);
                    }
                    if (data.map.getZoom() < minimalZoom) {
                        data.map.setZoom(minimalZoom);
                    }
                });

                data.cluster.setMaxZoom(args.maximalZoom-1);

                $(this).dequeue();
            });
        });
    }
};

$.fn.eventsMap = function(method) {
    if (methods[method]) {
        return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
    } else if (typeof method === 'object' || !method) {
        return methods.init.apply(this, arguments);
    } else {
        $.error( 'Method ' +  method + ' does not exist on jQuery.eventsMap' );
    }
};
})(jQuery);

Now it works like a charm, I was calling myObject.data('eventsmap') before it was set in init method btw I'm still unable to explain why I could see the object in the browser ... :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文