Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

javascript - Keypress in backbone.js?

It looks like key-press can only be executed on a focus element? I don't fully buy into that, there has to be a way to execute a key-press event similar to a click event?

I have a view that works with one item at a time. I have a mouseenter - mouseleave function that adds a class to the item the mouse is over. When the item receives that class I want to be able to use a key-press event to run a function on that item.

Obviously this is a slight obstacle but Id like to find out what I need to do. Below is an example view.

var PlayerView = Backbone.View.extend({
    tagName: 'div',

    events: {
        'click .points, .assists, span.rebounds, span.steals':'addStat',
        'mouseenter': 'enter',
        'mouseleave': 'leave',
        'keypress': 'keyAction'
    },

    enter: function() {
        this.$el.addClass('hover');
    },

    leave: function() {
        this.$el.removeClass('hover');
    },

    keyAction: function(e) {
        var code = e.keyCode || e.which;
        if(code == 65) { 
            alert('add assist')
        }
    }
});

So there isn't much logic here, but I am thinking I would write something like this

    keyAction: function(e) {
        var code = e.keyCode || e.which;
        if(code == 65) { 
            var addAssist = parseInt(this.model.get('assists')) + 1;        
            this.model.save({assists: addAssist});
        }
    }

Basically If I could figure out how to fire that keyAction method I should be good to go. So what are some caveats I am missing in executing some code like this? I am sure there are a few.

I do understand some of what is wrong with this code, it has no way of knowing when we run keypress in that view, I would have to add a conditional or something to find the active class, so when I execute the keypress it knows what model I am talking about, very vague description here but I get there is something wrong I am just not sure how to do this?

My solution

initialize: function() {
    this.listenTo(this.model, "change", this.render);
    _.bindAll(this, 'on_keypress');
    $(document).bind('keydown', this.on_keypress);
},

enter: function(e) {
    this.$el.addClass('hover');
},

leave: function(e) {
    this.$el.removeClass('hover');
},

on_keypress: function(e) {
    // A for assist
    if(e.keyCode == 65) { 
        if(this.$el.hasClass('hover')) {
            var addThis = parseInt(this.model.get('assists')) + 1;        
            this.model.save({assists: addThis});
        }
    }
    // R for rebound
    if(e.keyCode == 82) { 
        if(this.$el.hasClass('hover')) {
            var addThis = parseInt(this.model.get('rebounds')) + 1;        
            this.model.save({rebounds: addThis});
        }
    }
    // S for steal
    if(e.keyCode == 83) { 
        if(this.$el.hasClass('hover')) {
            var addThis = parseInt(this.model.get('steals')) + 1;        
            this.model.save({steals: addThis});
        }
    }
    // 1 for one point
    if(e.keyCode == 49) { 
        if(this.$el.hasClass('hover')) {
            var addMake = parseInt(this.model.get('made_one')) + 1;        
            this.model.save({made_one: addMake});

            var addOne = parseInt(this.model.get('points')) + 1; 
            this.model.save({points: addOne});
        }
    }
    // 2 for two points
    if(e.keyCode == 50) { 
        if(this.$el.hasClass('hover')) {
            var addMake = parseInt(this.model.get('made_two')) + 1;        
            this.model.save({made_two: addMake});

            var addTwo = parseInt(this.model.get('points')) + 2; 
            this.model.save({points: addTwo});
        }
    }
    // 2 for two points
    if(e.keyCode == 51) { 
        if(this.$el.hasClass('hover')) {
            var addMake = parseInt(this.model.get('made_three')) + 1;        
            this.model.save({made_three: addMake});

            var addThree = parseInt(this.model.get('points')) + 3; 
            this.model.save({points: addThree});
        }
    }
}

This is cool for my app because when the user hovers over the item the user can hit a key to add data, instead of clicking.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

So you are only going to be able to listen to the keypress in whichever element that you have the listener set on (or its children). And the keypress event is only going to fire if the element is focused. So I think the best solution for you would be to set focus on the element you are hovering over, then you can listen for the keypress, or better yet, listen to keydown because it behaves in a more standard way cross browser.

Here is a working JSFiddle demonstrating this technique: http://jsfiddle.net/DfjF2/2/

Only certain form elements accept focus. You can add contenteditable or tabindex attributes to the element, and that should allow pretty much any element to receive focus, but then the keydown event won't actually get fired! This is a browser specific issue. In my experience, a <span> will cause keydown and keyup events to be fired in every browser I have tested (Chrome, Firefox, IE, Safari, Android browser, Silk). So in the jsfiddle I added a span inside the target element, put focus on that, and added the keydown event listener to it.

So if you added an empty <span> into your view, your code could look something like this:

var PlayerView = Backbone.View.extend({
    tagName: 'div',

    events: {
        'click .points, .assists, span.rebounds, span.steals':'addStat',
        'mouseenter': 'enter',
        'mouseleave': 'leave',
        'keydown': 'keyAction'
    },

    enter: function() {
        this.$el.addClass('hover');
        var span = this.$el.find('span');
        span.attr('tabindex', '1').attr('contenteditable', 'true');
        span.focus();
    },

    leave: function() {
        this.$el.removeClass('hover');
        var span = this.$el.find('span');
        span.removeAttr('contenteditable').removeAttr('tabindex');
        span.blur();
    },

    keyAction: function(e) {
        var code = e.keyCode || e.which;
        if(code == 65) { 
            alert('add assist')
        }
    }
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...