Search code examples
javascriptjquerypolymerweb-component

ReferenceError: obj is not defined using webcomponents & polymer


This is my first project using web components and I'm a rookie at best with js/jquery, so I am not sure why this happening.

I have a custom element built in "search-form.html", all of my components and scripts are then brought in via a master "components.html" in the head of my index as such...

index.html:

<head>
    <meta charset='utf-8'>  
    <script src="/static/template/js/webcomponents.min.js"></script>
    <link rel="import" href="/static/template/components/components.html">
    <link rel="icon" type="image/png" href="/static/template/img/favicon.png">
</head>

components.html:

<!-- POLYMER MUST BE LOADED -->
<link rel="import" href="/static/template/polymer/polymer.html">

<!-- TEMPLATE SCRIPTS -->
<link rel="import" href="/static/template/components/scripts.html">
<!-- Loads jquery and other scripts -->

<!-- TEMPLATE COMPONENTS -->
<link rel="import" href="/static/template/components/search-form.html">

then the search-form.html looks like this:

<!-- Defines element markup -->
<dom-module id="search-form">
<template>
    <div class="input-prepend input-append">
        <form id="search" method="get" action="/property/search">
            <div class="btn-group">
                <button id="search-type" class="btn btn-inverse dropdown-toggle" data-toggle="dropdown">
                    Search by
                    <span class="caret"></span>
                </button>
                <ul class="dropdown-menu">
                    <li><a data-name="city" data-label="city">City</a></li>
                    <li><a data-name="zip" data-label="zip">Zip Code</a></li>
                    <li><a data-name="mls" data-label="mls">MLS Number</a></li>
                </ul>
            </div>
            <input id="input-tag" class="input-xlarge" type="text" placeholder="Select a search type..." data-provide="typeahead" value="" />
            <button type="submit" class="btn"><i class="fa fa-search"></i></button>
        </form>
    </div>
</template>

<script>
/********************************
/ TYPEAHEAD ARRAY
/*******************************/
var obj = {
    "city" : [],
    "zip" : [],
};

$(document).ready(function() {
    /*dynamic zipcode*/ 
    for(i=43000; i<=45999;i++){
        obj.zip.push({val: i.toString(), string: i.toString()});
    }
    for(i=48000; i<=49999;i++){
        obj.zip.push({val: i.toString(), string: i.toString()});
    }
});

/********************************
/ SEARCH TYPEAHEAD FUNCTION
/*******************************/
$(function searchTag($) {   

    var data = [];

    $('.dropdown-menu > li > a').on("click", function() {
        data = $(this).data('name');
    });

    var that = this;
    $('#input-tag').typeahead({
        source: function(query, process) {
                var results = _.map(obj[data], function(value) {
                    return value.val;
                });
                process(results);
        },
        highlighter: function(val) {
            var value = _.find(obj[data], function(p) {
                return p.val == val;
            });
            return value.string;
        },
        updater: function(val) {
            var value = _.find(obj[data], function(p) {
                return p.val == val;
            });
            that.setSelected(value);
            return value.string;
        }
    });
    this.setSelected = function(value) {
        $('#input-tag').val(value.string);
        //$('#input-tag').attr('data-value', value.val);
        $('#input-tag').data('value', value.val);
    };
});

/********************************
/ QUICK SEARCH TAG FUNCTION
/*******************************/
$(function () {

    var caret = ' <span class="caret"></span>';

    function searchSelect() {
        $('.dropdown-menu > li > a').on("click", function() {
            $('#search-type').html($(this).text() + caret);
            $('#input-tag').attr('placeholder', $(this).data('label'));
            $('#input-tag').attr('name', $(this).data('label'));
        });
    }searchSelect();
});

Polymer({
        is: 'search-form',
        created: function() {},
        ready: function() {},
        attached: function() {},
        detached: function() {},
        attributeChanged: function(name, type) {}
});
</script>
</dom-module>

so the var obj is declared in search-form.html

finally, because of the way our back end is written, I have to run a loop on index.html to get the array to be used in var obj for "city" : [],

that looks like this:

/*TYPEAHEAD ARRAY*/ 
//MUST BE RUN FROM SHELL BECAUSE OF THE TMPL LOOP
<!-- TMPL_LOOP Cities -->
    obj.city.push({val: "<!-- TMPL_VAR city_name -->", string: "<!-- TMPL_VAR city_name -->"})
<!-- /TMPL_LOOP -->

So now the problem. This all works without error in chrome, but I get the same error in FF, IE11, and Edge. That error is:

ReferenceError: obj is not defined
obj.city.push({val: "ALLEN PARK", string: "ALLEN PARK"})

Man I hope I documented this well enough for someone to help, because I have been pulling my hair out for hours before turning to stack :)


Solution

  • I think the imports are not loaded yet when you access the obj var in index.html, thus obj is undefined at this time. Since Chrome supports HTML imports natively, the imports are loaded earlier and it works there. Wrap the access to obj in HTMLImports.whenReady(callback). The callback will be called when all HTML imports have finished loading.

    HTMLImports.whenReady(function(){
        <!-- TMPL_LOOP Cities -->
        obj.city.push({val: "<!-- TMPL_VAR city_name -->", string: "<!-- TMPL_VAR city_name -->"})
        <!-- /TMPL_LOOP -->
    });