0

I am using jqvmap to show a map series (ifthq.com scroll low left). On the USA map, I have two states with values: LA and OH, both equal to 1.

The JSON used to feed jqvmap is: {"OH":1,"LA":1}.

The map shows, but does not fill correctly. My assumption is that linear normalizeFunction would result in two states at max, and the rest at min. This is not the case.

Since the US Map is over 50 elements, and the data is only two, how do I set "default" data to zero in the jqvmap? In other words, undefined states would be equal to zero?

Thanks.

UPDATE #1: Code for question: View definition. mbrmap is the result of the data pull:

@login_required
def index_view(request):
    enlisted = models.Subscription.objects.rankset("E").active().count()
    officer = models.Subscription.objects.rankset("O").active().count()
    civilian = models.Subscription.objects.rankset("C").active().count()
    lifer = models.Subscription.objects.lifer().active().count()
    subscriptions = models.Subscription.objects.all().order_by("-Modified")
    mbrcnt = models.Member.objects.values('State').annotate(c=Count('State')).exclude(State='')
    mbrcnt2 = models.Member.objects.values('Country').annotate(c=Count('Country')).exclude(Country='')
    mbrmap = dict([(type_and_count['State'], type_and_count['c']) for type_and_count in mbrcnt])
    mbrmap2 = dict([(type_and_count['Country'], type_and_count['c']) for type_and_count in mbrcnt2])
    mbrmap.update(mbrmap2)
    units = models.Unit.objects.values('Unit_name', 'Hull_type', 'Hull_number').annotate(c=Count('memberunit__Member'))
    context = {'mbrmap': mbrmap, 'enlisted': enlisted, 'officer': officer, 'civilian': civilian, 'lifer': lifer, 'units': units, 'Subscriptions': subscriptions}
    return render(request, 'index.html', context)

html:

<div class="portlet-body">
    <div id="region_statistics_loading">
        <img src="{% static "img/loading.gif" %}" alt="loading"/>
    </div>
    <div id="region_statistics_content" class="display-none">
        <div class="btn-toolbar margin-bottom-10">
            <div class="btn-group btn-group-circle" data-toggle="buttons">
                <a href="" class="btn grey-salsa btn-sm active">
                Members </a>
                <a href="" class="btn grey-salsa btn-sm">
                Units </a>
            </div>
            <div class="btn-group pull-right">
                <a href="" class="btn btn-circle grey-salsa btn-sm dropdown-toggle" data-toggle="dropdown" data-hover="dropdown" data-close-others="true">
                Select Region <span class="fa fa-angle-down">
                </span>
                </a>
                <ul class="dropdown-menu pull-right">
                    <li>
                        <a href="javascript:;" id="regional_stat_world">
                        World </a>
                    </li>
                    <li>
                        <a href="javascript:;" id="regional_stat_usa">
                        USA </a>
                    </li>
                    {% comment %}<li>
                        <a href="javascript:;" id="regional_stat_europe">
                        Europe </a>
                    </li>
                    <li>
                        <a href="javascript:;" id="regional_stat_russia">
                        Russia </a>
                    </li>
                    <li>
                        <a href="javascript:;" id="regional_stat_germany">
                        Germany </a>
                    </li>{% endcomment %}
                </ul>
            </div>
        </div>
        <div id="vmap_world" class="vmaps display-none">
        </div>
        <div id="vmap_usa" class="vmaps display-none">
        </div>
        {% comment %}<div id="vmap_europe" class="vmaps display-none">
        </div>
        <div id="vmap_russia" class="vmaps display-none">
        </div>
        <div id="vmap_germany" class="vmaps display-none">
        </div>{% endcomment %}
    </div>
</div>
<!-- PAGE LEVEL SPELLS -->
{% block PageSpells %}
    <!-- PLUGINS -->
    <script src="{% static "plugins/jqvmap/jqvmap/jquery.vmap.js" %}" type="text/javascript"></script>
    <script src="{% static "plugins/jqvmap/jqvmap/maps/jquery.vmap.russia.js" %}" type="text/javascript"></script>
    <script src="{% static "plugins/jqvmap/jqvmap/maps/jquery.vmap.world.js" %}" type="text/javascript"></script>
    <script src="{% static "plugins/jqvmap/jqvmap/maps/jquery.vmap.europe.js" %}" type="text/javascript"></script>
    <script src="{% static "plugins/jqvmap/jqvmap/maps/jquery.vmap.germany.js" %}" type="text/javascript"></script>
    <script src="{% static "plugins/jqvmap/jqvmap/maps/jquery.vmap.usa.js" %}" type="text/javascript"></script>
    <script src="{% static "plugins/jqvmap/jqvmap/data/jquery.vmap.sampledata.js" %}" type="text/javascript"></script>

    <!-- SPELLS -->
    <script src="{% static "js/index.js" %}" type="text/javascript"></script>
    <script src="{% static "plugins/uniform/jquery.uniform.min.js" %}" type="text/javascript"></script>
{% endblock %}

<!-- PAGE JQUERY -->
{% block Jquery %}
    var mapdata = {{ mbrmap|safe }};
    Index.init();
    Index.initCmdSelect();
    Index.initJQVMAP(mapdata); // init index page's custom scripts
{% endblock %}

javascript code:

initJQVMAP: function (mapdata) {
    if (!jQuery().vectorMap) {
        return;
    }

    var showMap = function (name) {
        jQuery('.vmaps').hide();
        jQuery('#vmap_' + name).show();
    }

    var setMap = function (name) {
        var data = {
            map: 'world_en',
            backgroundColor: null,
            borderColor: '#333333',
            borderOpacity: 0.5,
            borderWidth: 1,
            color: '#c6c6c6',
            enableZoom: true,
            hoverColor: '#c9dfaf',
            hoverOpacity: null,
            values: mapdata,
            normalizeFunction: 'linear',
            scaleColors: ['#C8EEFF', '#0071A4'],
            selectedColor: '#c9dfaf',
            selectedRegion: null,
            showTooltip: true,
            onLabelShow: function (event, label, code) {

            },
            onRegionOver: function (event, code) {
                if (code == 'ca') {
                    event.preventDefault();
                }
            },
            onRegionClick: function (element, code, region) {
                if (typeof mapdata[code.toUpperCase()] === 'undefined') {
                    var sval = 0;
                } else {
                    var sval = mapdata[code.toUpperCase()]
                }
                var message = 'You clicked "' + region + '" which has the code: ' + code.toUpperCase() + ' and value:  ' + sval;
                alert(message);
            }
        };

        data.map = name + '_en';
        var map = jQuery('#vmap_' + name);
        if (!map) {
            return;
        }
        map.width(map.parent().parent().width());
        map.show();
        map.vectorMap(data);
        map.hide();
    }

    setMap("world");
    setMap("usa");
    //setMap("europe");
    //setMap("russia");
    //setMap("germany");
    showMap("world");

    jQuery('#regional_stat_world').click(function () {
        showMap("world");
    });

    jQuery('#regional_stat_usa').click(function () {
        showMap("usa");
    });

    jQuery('#regional_stat_europe').click(function () {
        showMap("europe");
    });
    jQuery('#regional_stat_russia').click(function () {
        showMap("russia");
    });
    jQuery('#regional_stat_germany').click(function () {
        showMap("germany");
    });

    $('#region_statistics_loading').hide();
    $('#region_statistics_content').show();
},

Of note, the initJQVMAP function is a method in the index object:

var Index = function() {....

It is initialized by the Index.initJQVMAP(mapdata); function call. Thanks.

arcee123
  • 101
  • 9
  • 41
  • 118
  • Can you post some code please? – Marc Oct 29 '15 at 15:01
  • Thank you very much for attending to this this for me. – arcee123 Oct 29 '15 at 15:23
  • I believe the problem here is in the javascript. in case you are not familiar with django. – arcee123 Oct 29 '15 at 15:27
  • What are you trying to achieve exactly? Fill the JSON with all other states and `0` value? – Diego Oct 29 '15 at 15:29
  • well, what I'm actually hoping is that jqvmap will assume 0 when there's no value. Otherwise, I'll have to reset my data models to have a table filled with zeros. – arcee123 Oct 29 '15 at 15:30
  • in this case, I only have two entities with values. This is because I only have two records that count in my database. – arcee123 Oct 29 '15 at 15:31
  • I can't find documentation about `values` option. What are you trying to do with it? – Diego Oct 29 '15 at 15:36
  • according to the instructions, the two values: normalizefunction and scaleColors, is designed to "heatmap" the area. for example, the higher values are closer to the right color in scaleColors. The problem here is that this is not competing 0 vs 1. It's competing undefined vs. 1, because there are no other states with values. therefore, normalizefunction is only competing against 1 and itself. ergo, no color. – arcee123 Oct 29 '15 at 15:41
  • What exactly do you want to become `0`? – Oriol Oct 29 '15 at 15:50
  • @arcee123, In that case I believe the first code on my answer might be what you are looking for – Diego Oct 29 '15 at 21:02

2 Answers2

1

You could try changing the colors after creating the map:

var newData = {};
for (var key in mapdata)
    newData[key.toLowerCase()] = '#0071A4';
map.vectorMap('set', 'colors', newData);

Here there is a working sample.

Edit

I've also found this different solution:

var arrStates = [];
for (var key in mapdata)
    arrStates.push(key);
map.vectorMap('set', 'colors', arrStates, '#0071A4');
Diego
  • 16,436
  • 26
  • 84
  • 136
  • Hi Diego, thank you very much for this solution. Is there anyway to re-integrate the `scaleColors: ['#C8EEFF', '#0071A4'],` back into this movement, so the colors are varied? right now, the values are 1 and 0, but what happens if you have `{'OH':3, ''LA':1}`? this would need to be two shades. Thanks. – arcee123 Oct 31 '15 at 03:19
  • DIego, thank you so much. I wish I could award more bounty. While you did change colors, Rusty's solution worked as designed. Thanks. – arcee123 Oct 31 '15 at 03:46
1

You can use $.extend() to combine two objects, overwriting the values of one if they exist in the other (documentation here). For example:

var mySmallData = {
  "OH": 1,
  "LA": 1
};
var DEFAULTS = {
  "OH": 0,
  "LA": 0,
  "WA": 0,
  "ID": 0,
  // etc.
};

var fullData = $.extend({}, DEFAULTS, mySmallData);

fullData would now contain:

{
  "OH": 1,
  "LA": 1,
  "WA": 0,
  "ID": 0
}

This way, you have one object that has all of your defaults and you never have to mess with it. Your sparse object can have as few data points as you want, and it will always get expanded to the full set of states.

RustyTheBoyRobot
  • 5,891
  • 4
  • 36
  • 55