Skip to content

Commit

Permalink
Added hotkeys for actions.
Browse files Browse the repository at this point in the history
  • Loading branch information
dmorrill10 committed Sep 8, 2012
1 parent ae7d5c1 commit fb65e4e
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 21 deletions.
45 changes: 45 additions & 0 deletions app/assets/javascripts/jquery.hotkeys/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#About
**jQuery Hotkeys** is a plug-in that lets you easily add and remove handlers for keyboard events anywhere in your code supporting almost any key combination.

This plugin is based off of the plugin by Tzury Bar Yochay: [jQuery.hotkeys](http://github.com/tzuryby/hotkeys)

The syntax is as follows:

$(expression).bind(types, keys, handler);
$(expression).unbind(types, handler);

$(document).bind('keydown', 'ctrl+a', fn);

// e.g. replace '$' sign with 'EUR'
$('input.foo').bind('keyup', '$', function(){
this.value = this.value.replace('$', 'EUR');
});

## Types
Supported types are `'keydown'`, `'keyup'` and `'keypress'`

## Notes

If you want to use more than one modifiers (e.g. alt+ctrl+z) you should define them by an alphabetical order e.g. alt+ctrl+shift

Hotkeys aren't tracked if you're inside of an input element (unless you explicitly bind the hotkey directly to the input). This helps to avoid conflict with normal user typing.

## jQuery Compatibility

Works with jQuery 1.4.2 and newer.

It known to be working with all the major browsers on all available platforms (Win/Mac/Linux)

* IE 6/7/8
* FF 1.5/2/3
* Opera-9
* Safari-3
* Chrome-0.2

### Addendum

Firefox is the most liberal one in the manner of letting you capture all short-cuts even those that are built-in in the browser such as `Ctrl-t` for new tab, or `Ctrl-a` for selecting all text. You can always bubble them up to the browser by returning `true` in your handler.

Others, (IE) either let you handle built-in short-cuts, but will add their functionality after your code has executed. Or (Opera/Safari) will *not* pass those events to the DOM at all.

*So, if you bind `Ctrl-Q` or `Alt-F4` and your Safari/Opera window is closed don't be surprised.*
99 changes: 99 additions & 0 deletions app/assets/javascripts/jquery.hotkeys/jquery.hotkeys.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* jQuery Hotkeys Plugin
* Copyright 2010, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Based upon the plugin by Tzury Bar Yochay:
* http://github.com/tzuryby/hotkeys
*
* Original idea by:
* Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
*/

(function(jQuery){

jQuery.hotkeys = {
version: "0.8",

specialKeys: {
8: "backspace", 9: "tab", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause",
20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home",
37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del",
96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7",
104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/",
112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8",
120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 191: "/", 224: "meta"
},

shiftNums: {
"`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&",
"8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": "\"", ",": "<",
".": ">", "/": "?", "\\": "|"
}
};

function keyHandler( handleObj ) {
// Only care when a possible input has been specified
if ( typeof handleObj.data !== "string" ) {
return;
}

var origHandler = handleObj.handler,
keys = handleObj.data.toLowerCase().split(" ");

handleObj.handler = function( event ) {
// Don't fire in text-accepting inputs that we didn't directly bind to
if ( this !== event.target && (/textarea|select/i.test( event.target.nodeName ) ||
event.target.type === "text") ) {
return;
}

// Keypress represents characters, not special keys
var special = event.type !== "keypress" && jQuery.hotkeys.specialKeys[ event.which ],
character = String.fromCharCode( event.which ).toLowerCase(),
key, modif = "", possible = {};

// check combinations (alt|ctrl|shift+anything)
if ( event.altKey && special !== "alt" ) {
modif += "alt+";
}

if ( event.ctrlKey && special !== "ctrl" ) {
modif += "ctrl+";
}

// TODO: Need to make sure this works consistently across platforms
if ( event.metaKey && !event.ctrlKey && special !== "meta" ) {
modif += "meta+";
}

if ( event.shiftKey && special !== "shift" ) {
modif += "shift+";
}

if ( special ) {
possible[ modif + special ] = true;

} else {
possible[ modif + character ] = true;
possible[ modif + jQuery.hotkeys.shiftNums[ character ] ] = true;

// "$" can be triggered as "Shift+4" or "Shift+$" or just "$"
if ( modif === "shift+" ) {
possible[ jQuery.hotkeys.shiftNums[ character ] ] = true;
}
}

for ( var i = 0, l = keys.length; i < l; i++ ) {
if ( possible[ keys[i] ] ) {
return origHandler.apply( this, arguments );
}
}
};
}

jQuery.each([ "keydown", "keyup", "keypress" ], function() {
jQuery.event.special[ this ] = { add: keyHandler };
});

})( jQuery );
11 changes: 11 additions & 0 deletions app/assets/javascripts/project_specific/hotkey.js.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Hotkey =
bind: (element, key) ->
$(document).bind('keypress', key, (evt)->
$(element).click()
)

Hotkey.bind('#fold.button', 'a')
Hotkey.bind('#pass.button', 's')
Hotkey.bind('#wager.button', 'd')
Hotkey.bind('#leave.button', 'q')
Hotkey.bind('#next.button', 'f')
5 changes: 3 additions & 2 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ module ApplicationHelper
# @param [Hash] options = Hash.new
def button(button_string, url, options = Hash.new)
form_tag url, :remote => true do
options[:class] = 'button'
s = if options[:confirm]
submit_tag button_string, :class => 'button', :data => { :confirm => options[:confirm] }, disabled: options[:disabled]
submit_tag button_string, options
else
submit_tag button_string, :class => 'button', disabled: options[:disabled]
submit_tag button_string, options
end
# @todo Use centralized string names rather than local ones
s << number_field_tag(:amount_field, 1) if options[:amount_field]
Expand Down
12 changes: 6 additions & 6 deletions app/views/new_game/_rejoin_match_form.html.haml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#rejoin_match_form
= form_tag rejoin_match_url, remote: true do
= label_tag 'Match name'
= text_field_tag 'match_name'
- rejoin_match_label = 'Rejoin match'
= submit_tag rejoin_match_label, class: 'button', disable_with: rejoin_match_label
.hidden= hidden_game_parameter_form
= form_tag rejoin_match_url, remote: true do
= label_tag 'Match name'
= text_field_tag 'match_name'
- rejoin_match_label = 'Rejoin match'
= submit_tag rejoin_match_label, class: 'button', data: { disable_with: rejoin_match_label }
.hidden= hidden_game_parameter_form
29 changes: 16 additions & 13 deletions app/views/player_actions/_index.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
setTimeout(
(-> $('#hidden_update_match_state').submit()),
100
)

- leave_match_confirmation_message = "Are you sure you want to leave this match?"
- leave_match_label = "Leave match"
- leave_match_button = button leave_match_label, leave_game_url, match_id: @match_id, confirm: leave_match_confirmation_message, data: { disable_with: leave_match_label }
)
- def leave_match_button(options={})
- leave_match_confirmation_message = "Are you sure you want to leave this match?"
- leave_match_label = "Leave match"
- button leave_match_label, leave_game_url, {match_id: @match_id, data: { confirm: leave_match_confirmation_message, disable_with: leave_match_label }}.merge(options)
.toolbar
.toolbar_item
.meta_action
= leave_match_button
= leave_match_button id: 'leave'

%ul.chip_balances
%li.title= "#{@match.match_name} #{@match_slice.hand_number+1} / #{@match.number_of_hands}"
Expand Down Expand Up @@ -72,7 +72,7 @@
- elsif next_hand_button_should_be_visible
.meta_action
- next_hand_label = "Next hand"
= update_state_form @match_id, @match_slice_index, next_hand_label, disabled: !@hand_ended || @match_ended, data: { disable_with: next_hand_label }
= update_state_form @match_id, @match_slice_index, next_hand_label, disabled: !@hand_ended || @match_ended, data: { disable_with: next_hand_label }, id: 'next'
- else
- if @is_no_limit
.wager_amount_slider
Expand All @@ -91,14 +91,14 @@
= f.input :match_slice_index, as: :hidden, input_html: { value: @match_slice_index }
= f.input :poker_action, as: :hidden, input_html: { value: 'f' }
- fold_label = 'Fold'
= submit_tag fold_label, class: 'button', disabled: !(@users_turn_to_act && @legal_actions.include?('f')), data: { disable_with: fold_label }
= submit_tag fold_label, class: 'button', disabled: !(@users_turn_to_act && @legal_actions.include?('f')), data: { disable_with: fold_label }, id: 'fold'
.action
= simple_form_for @user_poker_action, url: take_action_url, remote: true, validate: true do |f|
- pass_action_button_label = if (@legal_actions.include?('c') && @amount_for_user_to_call > 0) then (if @is_no_limit then "Call (#{@amount_for_user_to_call})" else 'Call' end) else 'Check' end
= f.input :match_id, as: :hidden, input_html: { value: @match_id }
= f.input :match_slice_index, as: :hidden, input_html: { value: @match_slice_index }
= f.input :poker_action, as: :hidden, input_html: { value: 'c' }
= submit_tag pass_action_button_label, class: 'button', disabled: !@users_turn_to_act, data: { disable_with: pass_action_button_label }
= submit_tag pass_action_button_label, class: 'button', disabled: !@users_turn_to_act, data: { disable_with: pass_action_button_label }, id: 'pass'
.action
= simple_form_for @user_poker_action, url: take_action_url, remote: true, validate: true do |f|
- make_wager_button_label = if @legal_actions.include?('b') then 'Bet' else 'Raise' end
Expand All @@ -108,11 +108,12 @@
= f.input :poker_action, as: :hidden, input_html: { value: 'r' }
- if @is_no_limit
= f.input :modifier, as: :integer, label: false, input_html: { value: @minimum_wager }
= submit_tag make_wager_button_label, class: 'button', id: 'with_modifier', disabled: !@users_turn_to_act, data: { disable_with: make_wager_button_label }
= submit_tag make_wager_button_label, class: ['button', 'with_modifier'], id: 'wager', disabled: !@users_turn_to_act, data: { disable_with: make_wager_button_label }

:coffeescript
ChipStackMutator.adjustAmountFontSizeOfAllStacks()

# Inteface scale adjustment
adjustScale = (elementToScale) ->
widthRatio = $(window).width() / elementToScale.width()
heightRatio = ($(window).height() - $('.toolbar').height()) / elementToScale.height()
Expand Down Expand Up @@ -140,19 +141,21 @@

originalSliderWidth = 275 # Hardcoded slider width separate from that set in CSS, not sure how to get around this
slider.width(originalSliderWidth * smallestRatio)

adjustScale($('.game_interface'))
jQuery(window).resize(->
adjustScale($('.game_interface'))
)

# Disable all buttons upon one being clicked
$('.button').click(->
return if this.id is 'leave'

$('.button').attr("disabled", true)
$(this).attr("disabled", false)
)

$('.button#with_modifier').click(->

# Adjust wager amount
$('.button.with_modifier').click(->
wager_to_amount_over_round = $('input#user_poker_action_modifier').val()
wager_to_amount_over_hand = parseInt(wager_to_amount_over_round) + parseInt("#{@amount_user_has_contributed_over_previous_rounds}")

Expand Down

0 comments on commit fb65e4e

Please sign in to comment.