0

yahoo placemaker からツイートをループした後、つぶやきを div にロードしようとしています。それらは div にロードされていますが、それらによって表示される情報はプレースメーカーの最終結果です。

これはコードです..

            function getLocation(user, date, profile_img, text,url) {
            var templates = [];
            templates[0] = '<div><div></div><h2 class="firstHeading">'+user+'</h2><div>'+text+'</div><div><p><a href="' + url + '"target="_blank">'+url+'</a></p></div><p>Date Posted- '+date+'</p></div>';
            templates[1] = '<table width="320" border="0"><tr><td class="user"  colspan="2" rowspan="1">'+user+'</td></tr><tr><td width="45"><a href="'+profile_img+'"><img src="'+profile_img+'" width="55" height="50"/></a></td><td width="186">'+text+'<p><a href="' + url + '"target="_blank">'+url+'</a></p></td></tr></table><hr>';
            templates[2] = '<div><div></div><h2 class="firstHeading">'+user+'</h2><div>'+text+'</div><div><p><a href="' + url + '"target="_blank">'+url+'</a></p></div><p>Date Posted- '+date+'</p></div>';
            templates[3] = '<table width="320" border="0"><tr><td class="user"  colspan="2" rowspan="1">'+user+'</td></tr><tr><td width="45"><a href="'+profile_img+'"><img src="'+profile_img+'" width="55" height="50"/></a></td><td width="186">'+text+'<p><a href="' + url + '"target="_blank">'+url+'</a></p></td></tr></table><hr>';
                        var geocoder = new google.maps.Geocoder();
                Placemaker.getPlaces(text, function (o) {
                    console.log(o);
                    if (!$.isArray(o.match)) {
                        var latitude = o.match.place.centroid.latitude;
                        var longitude = o.match.place.centroid.longitude;
                        var myLatLng = new google.maps.LatLng(latitude, longitude);
                        var marker = new google.maps.Marker({
                            icon: profile_img,
                            title: user,
                            map: map,
                            position: myLatLng
                        });

                      var infowindow = new google.maps.InfoWindow({
                          content: templates[0].replace('user',user).replace('text',text).replace('url',url).replace('date',date)
                      });
                      var $tweet = $(templates[1].replace('%user',user).replace(/%profile_img/g,profile_img).replace('%text',text).replace('%url',url));
                      $('#user-banner').css("visibility","visible");$('#news-banner').css("visibility","visible");
                      $('#news-tweets').css("overflow","scroll").append($tweet);
                      function openInfoWindow() {
                          infowindow.open(map, marker);
                      }
                      google.maps.event.addListener(marker, 'click', openInfoWindow);
                      $tweet.find(".user").on('click', openInfoWindow);
                        bounds.extend(myLatLng);
                    }
                });
            }
4

2 に答える 2

1

ああ、

Placemaker.jsいくつかの実験の後、複数の同時リクエストを処理できないという問題を突き止めました。クロージャの問題を克服してループ生成データを記憶できると考えたくなるかもしれませんが、これはうまくいきません。修正を適用する必要があるためPlacemaker、jQuery プラグインとしてリファクタリングすることにしました。promisejQuery は、メソッドからa を返す可能性を提供し、getPlacesjQuery のネイティブなどと同様にし$.ajax()ます$.get()

ヤフー!jQuery プラグインとしての Placemaker.js

/* ******************************************************************************
 * Yahoo! Placemaker.js factored as a jQuery Plugin
 * ******************************************************************************
 * by Beetroot-Beetroot: http://stackoverflow.com/users/1142252/beetroot-beetroot
 * ******************************************************************************
 * For example of usage, see : http://stackoverflow.com/questions/12253544/
 * ******************************************************************************
 * All rights reserved
 * Please keep this attribution intact
 * ******************************************************************************
 */
(function($){
    // **********************************
    // ***** Start: Private Members *****
    var pluginName = 'Placemaker';
    var config = {
        appID: ''
    }
    // ***** Fin: Private Members *****
    // ********************************

    // *********************************
    // ***** Start: Public Methods *****
    var methods = {
        config: function(obj) {
            $.extend(config, obj);
        },
        getPlaces: function(data) {
            var that = this;//jQuery object
            var def = new $.Deferred();
            if(config.appID === '') {
                def.rejectWith(this, [{message: pluginName + ' plugin application ID is not set'}]);
                return def.promise();
            }
            var query = [
                'select * from geo.placemaker where documentContent="' + data.text + '" and documentType="text/plain"'
            ];
            if(data.locale) {
                query.push('and inputLanguage="' + data.locale + '"');
            }
            query.push('and appid="' + config.appID + '"');
            var url = [
                'http://query.yahooapis.com/v1/public/yql?q=' + encodeURIComponent(query.join(' ')),
                'format=json',
                'env=http%3A%2F%2Fdatatables.org%2Falltables.env',
                'callback=?' // callback=Placemaker.retrieve ????
            ];
            $.ajax({
                url: url.join('&'),
                type: 'GET',
                dataType: 'JSON',
                cache: false
            }).done(function(o) {
            if(o.query && o.query.results && o.query.results.matches) {
                    def.resolveWith(that, [o.query.results.matches, data]);
                }
                else {
                    def.rejectWith(that, [{message:'no locations found'}]);
                }
            }).fail(function(jqXHR, textStatus, errorThrown) {
                def.rejectWith(that, [{message: textStatus}]);
            });
            return def.promise();
        }
    };
    // ***** Fin: Public Methods *****
    // *******************************

    // *****************************
    // ***** Start: Supervisor *****
    $.fn[pluginName] = 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 in jQuery.' + pluginName );
        }
    };
    // ***** Fin: Supervisor *****
    // ***************************
})( jQuery );

appID の設定

You can hard-code your appID in your own copy of the plugin or set it like this :

    $().Placemaker('config', {'appID': '..........'});

.Placemaker()jQuery オブジェクトで呼び出す必要があることに注意してください。「config」メソッドの場合は、どのセレクターでも機能するため、空の jQuery オブジェクトで$()十分です。

プラグインの使用

プラグイン呼び出しを含む残りのコードは、次のようになります。

$(function() {
    // *** fixed data ***
    var mapOptions = {
        center: new google.maps.LatLng(35.74651, -39.46289),
        zoom: 2,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    var templates = [];
    templates[0] = '<div><h2 class="firstHeading">%user</h2><div>%text</div><div><a href="%url" target="_blank">%url</a></div><div>Date Posted- %date</div></div>';
    templates[1] = '<table width="320" border="0"><tr><td class="user" colspan="2">%user</td></tr><tr><td width="45"><a href="%profile_img"><img src="%profile_img" width="55" height="50"/></a></td><td width="186">%text<p><a href="%url" target="_blank">%url</a></p></td></tr></table><hr/>';
    templates[3] = "https://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&include_rts=false&screen_name=%val&count=10&callback=?";
    $$ = { //cache of jQuery objects
        news_tweets: $("#news-tweets"),
        user_banner: $('#user-banner')
    };

    // *** functions ***
    function news_tweets(value1) {
        $$.news_tweets.empty();
        var bounds = new google.maps.LatLngBounds(); //??
        var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
        $.getJSON(templates[3].replace('%val', value1), function(data) {
            var d, len = data.length;
            for (var i = 0; i < len; i++) {
                var item = data[i];
                d = {
                    text: item.text,
                    user : item.user.name,
                    date: item.created_at,
                    profile_img: item.user.profile_image_url,
                    url: (item.entities && item.entities.urls && item.entities.urls.length) ? item.entities.urls[0].url : '',
                    locale: null
                }
                d.$tweet = $(templates[1].replace('%user', d.user).replace(/%profile_img/g, d.profile_img).replace('%text', d.text).replace(/%url/g, d.url))
                    .appendTo($$.news_tweets.css("overflow", "scroll"))
                    .find(".user")
                    .Placemaker('getPlaces', d)  //.Placemaker('getPlaces') returns a promise
                    .done(function(o, d) {
                        var m = ($.isArray(o.match) ? o.match[0] : o.match) || {};
                        if(m.place) {
                            var myLatLng = new google.maps.LatLng(m.place.centroid.latitude, m.place.centroid.longitude);
                            var marker = new google.maps.Marker({
                                icon: d.profile_img,
                                title: d.user,
                                map: map,
                                position: myLatLng
                            });
                            var infowindow = new google.maps.InfoWindow({
                                content: templates[0].replace('%user', d.user).replace('%text', d.text).replace(/%url/g, d.url).replace('%date', d.date)
                            });
                            function openInfoWindow() {
                                infowindow.open(map, marker);
                            }
                            google.maps.event.addListener(marker, 'click', openInfoWindow);
                            this.each(function() { //`this` is already a jQuery object. Re-wrapping as `$(this)` is not necessary.
                                $(this).on('click', openInfoWindow).css({'color':'#900', 'text-decoration':'underline', 'cursor':'pointer'});//$(this) is an individual tweet in #news_tweets.
                            });
                            bounds.extend(myLatLng); //??
                        }
                    }).fail(function(err) {
                        console.log(err.message);
                });
            }
        });
    }

    // *** event handlers ***
    $("#newsTypes").on('click', 'img', function() {
        news_tweets($(this).data('type'));
        //user_tweets("euronews");
    });
});

これの中心には、次の構造があります。

for(...) {
    var d = {...}; //object map comprising both data and options
    $(htmlString).appendTo(...).find(...).Placemaker('getPlaces', d).done(fn{}).fail(fn{});
}

次のことに注意することが重要です。

  • jQuery メソッド チェーンは、標準の jQuery オブジェクトから始まります。
  • from .Placemaker('getPlaces', d)、チェーン内のメソッドは jQuery promise オブジェクトを返します。
  • .done().fail()ハンドラーの両方でthis、元の標準 jQuery オブジェクトと同等です。
  • 式の 2 番目の引数として渡されたデータ マップは、ハンドラー.Placemaker('getPlaces', d)の 2 番目の引数として再表示されます。.done()この機能により.Placemaker('getPlaces', d)、具体的にデータをクロージャーに入れたり、.data(). この点で、「getPlaces」メソッドはクロージャーとして効果的に機能するだけでなく、必要な非同期ルックアップ動作を提供します。

これはすべて、あなたの視点に応じて、完全に混乱していると判断されるか、完全に賢いと判断されます.

于 2012-09-05T20:07:43.277 に答える
0

私が見るところ、あなたのコードは.replace()反復ごとに div の内容に書き込まれます。テンプレート配列にインデックスを追加する必要があります。

次のようなものを試してください:

var index=0;

var templates = [];
templates[index]={
'0':'<div><div></div><h2....',
'1':'<table width="320".....',
'2':'<div><div></div><h2....',
'3':'<table width="320"....'
}

次に、Placemaker.getPlacesブロックを に入れます。for loop テンプレートを で更新しますtemplates[index]["0"]=whatever。これがあなたが追求すべき論理だと思います。これがすべて役立つことを願っています。

于 2012-09-03T21:41:34.590 に答える