0

Am trying to build a simple widget using bootstrap popover

UW.UI.ProjectMember = {

dropdown: ".project-member-select-dropdown",
input: ".member-search-field",

options: {
    container: $('.project-member-select'),
    trigger: "click",
    minChar: 2
},

renderTemplate: function() {
    var template = '<div class="project-member-picker">'+
                        '<div class="project-member-search-box">'+
                            '<input type="text" class="member-search-field input-block-level" placeholder="Enter a name">'+
                            '<ul class="project-member-select-dropdown"></ul>'+
                        '</div>'+
                        '<div><p>You can invite your colleagues to use UberWork with you</p></div>'+
                    '</div>';

    this.options.container.append(template);

    return this;
},

initPopover: function() {
    var _this = this;

    $(".add-member-btn").popover({
        html: true,
        placement: "bottom",
        trigger: _this.options.trigger,
        container: '#window',
        content: _this.build()
    });
},

build: function() {

    return $('.project-member-picker').html();
},

delegateEvents: function() {
    var _this = this;

    $(document).on("keydown",'.popover .member-search-field', function(event) {
        _this.processInput(event, _this);
    });

    $(document).on("click", '.popover li.member', function(event) {
        _this.addToken(event, _this);
    });

    $(document).on("click", '.popover .project-members ul li a.remove', function(event) {
        _this.deleteToken(event, _this);
    });
},

showDropdown: function() {
    $(this.dropdown).css({
                position: "absolute",
                zindex: 999
            }).show();
},  

hideDropdown: function() {
    $(this.dropdown).hide().empty();
},

processInput: function(event, that) {
    var input = $(event.currentTarget),
    inputValue = input.val(), timeout;

    if(inputValue.length >= 1) {
        that.showSearchActivity();

        clearTimeout(timeout);
        timeout = setTimeout(function() {
            that.runSearch(inputValue.toLowerCase())
        }, 300);
    }
    else {
        that.hideDropdown();
    }
},

showSearchActivity: function() {
    $(this.dropdown).html('<p>Searching...</p>');
    this.showDropdown();
},

runSearch: function(query) {
    var results = $.grep(UW.Members, function (row) {
        return[row.name].toString().toLowerCase().indexOf(query.toLowerCase()) > -1;
    });

    this.populateDropdown(query, results);
},

populateDropdown: function(query, results) {
    var _this = this;

    if(results && results.length) {
        $(this.dropdown).empty();
        this.hideDropdown();

        $.each(results, function (index, value) {
            if(value.photo == "")
                var photo = UW.Constants.avatar;
            else
                var photo = value.photo;

            var template = '<li class="member" data-id="'+value.user_id+'">'+
                                '<div class="member-avatar pull-left"><img src="'+photo+'"></div>'+
                                '<div class="member-name pull-left">'+value.name+'</div>'+
                            '</li>';

            $(_this.dropdown).append(template);
        });

        this.showDropdown();
    }else {
        $(this.dropdown).html('<p>No results</p>');
        this.showDropdown();
    }
},

addToken: function(event, that) {

    var el = $(event.currentTarget);
    var id = el.attr('data-id');

    var user = {
        name: $(el).find('div.member-name').html(),
        photo: $(el).find('div.member-avatar').find('img').attr('src')
    };

    //update member list
    var members = this.options.container.find('div.project-members ul.member-avatars');


        if(members.find('li[data-id="'+id+'"]').length == 0) {

            members.append('<li data-id="'+id+'"><img src="'+user.photo+'" title="'+user.name+'"></li>');
        }

    //clear input
    $(that.input).val('');

    //Hide dropdown
    this.hideDropdown();
},

deleteToken: function(event, that) {

    event.preventDefault();
},

init: function() {
    this.renderTemplate();
    this.initPopover()
    this.delegateEvents();
}

I know am posting alot of code, anyway i am instantiating the UW.UI.ProjectMember class from a backbone view. When the $(".add-member-btn") element is clicked to trigger the popover, everything works fine for the first time but when element is clicked again to hide the popover the chrome console shows this error " Uncaught RangeError: Maximum call stack size exceeded". What could i be doing wrong? Any help will be appreciated.

MrFoh
  • 2,693
  • 9
  • 42
  • 77
  • Somewhere in your code you have something that is calling something else in a loop of some sort, causing so many calls that the call stack reaches it's limit, and an error occurs. It's hard to tell exactly where that is, you should set some breakpoints, do some console logs etc. to try and figure out what you're calling that many times. – adeneo Jun 15 '13 at 14:12
  • I can't spot any obvious recursions, therefore no obvious answer to the problem. Observation: in `processInput()`, as a freshly declared local var, `timeout` will always be undefined when `clearTimeout(timeout)` is called. I don't think this will fix the problem though. – Beetroot-Beetroot Jun 15 '13 at 16:23
  • I've combed through my code and i can't find any recursion too. – MrFoh Jun 15 '13 at 17:58

0 Answers0