How to detect a button press with Gamepad API? - javascript

I am trying to write a web page where I can detect button presses on a Xbox controller and show a user a boolean value based on the button pressed. Right now, I can detect a controller being connected and show that as a string. The documentation says to use this code to detect a button press here:
var isPressed = navigator.getGamepads()[0].pressed;
but Chrome shows this error when using it:
Uncaught TypeError: Cannot read property 'pressed' of null
The error is linked to the .pressed part of the above line of code. All the documentation is on the Mozilla site, so I'm assuming they used FireFox when writing the tutorials.
What I ideally want to end up with is this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<h id="button"></h>
<h id="gpInfo"></h>
<script>
var i = 1;
window.addEventListener("gamepadconnected", function(e) {
var gp = navigator.getGamepads()[e.gamepad.index];
document.getElementById("gpInfo").innerHTML = ("A " + gp.id + " was successfully detected! There are a total of " + gp.buttons.length + " buttons.")
//alert("A " + gp.id + " was successfully detected!")
});
var isPressed = navigator.getGamepads()[0].pressed;
document.getElementById("button").innerHTML = isPressed;
</script>
<!-- <script type="text/javascript" src="gamepadtest.js"></script> -->
</head>
</html>
The code would print a boolean value on the screen for users to see when they press a button.
This is my first time working with JavaScript and HTML. If you could make your answer noob-friendly that would be great! Documentation for Gamepad API and for GamepadButton

You shouldn't reference the Gamepad object until the gamepadconnected event has been thrown. Also, you'll need a loop to poll the button value. Here's some revised code:
var i = 1;
window.addEventListener("gamepadconnected", function(e) {
var gp = navigator.getGamepads()[e.gamepad.index];
document.getElementById("gpInfo").innerHTML = ("A " + gp.id + " was successfully detected! There are a total of " + gp.buttons.length + " buttons.")
//alert("A " + gp.id + " was successfully detected!")
setInterval(function(){
isPressed = gp.buttons[0].pressed;
document.getElementById("button").innerHTML = isPressed;
}, 100)
});

I don't have enough reputation to just add a comment to Caleb Denio's answer, but regarding Nathan's comment on that answer:
I have used your example to listen for 20 buttons and i can detect each button, but once i have pressed one, it will not change another result for a different button.
I see the same behaviour on Chrome 90. Specifically, a new GamepadList instance, containing new Gamepad instances, all seem to be created each time the state of any gamepad changes (e.g. which of its buttons are pressed).
You can test it with this:
var gamepads = null;
function callback() {
var new_gamepads = navigator.getGamepads();
if(new_gamepads !== gamepads) {
console.log('New GamepadList!', new_gamepads);
gamepads = new_gamepads;
}
}
var interval = setInterval(callback, 100);
...for me, that logs 'New GamepadList!' each time I press/release a button.
Long story short, you need to poll navigator.getGamepads() each frame in order to detect changes in gamepad state.
A minimalist fix for Caleb Denio's answer would therefore be:
var i = 1;
window.addEventListener("gamepadconnected", function(e) {
var gp = navigator.getGamepads()[e.gamepad.index];
document.getElementById("gpInfo").innerHTML = ("A " + gp.id + " was successfully detected! There are a total of " + gp.buttons.length + " buttons.")
//alert("A " + gp.id + " was successfully detected!")
setInterval(function(){
// ===> Get a fresh GamepadList! <===
var gp = navigator.getGamepads()[e.gamepad.index];
isPressed = gp.buttons[0].pressed;
document.getElementById("button").innerHTML = isPressed;
}, 100)
});

Related

Selected value from html select menu

I'm trying to make clicking the battle button print "You have slain" + selected option + What I have now works for the first option, but if you select a different option in the dropdown and click battle it still says Fly.
Fiddle
var mon = document.getElementById('monsters');
var monster =mon.options[mon.selectedIndex].text;
$('#battle').click(function() {
document.getElementById('dam').innerHTML = "You have hit the " + monster + " for 5 damage";
});
In your solution, you have declared the values of the selected value globally which is set only once during the document load. In order to calculate the right value, you have to declare them locally during the button click.
$('#battle').click(function() {
var mon = document.getElementById('monsters');
var monster =mon.options[mon.selectedIndex].text;
document.getElementById('dam').innerHTML = "You have hit the " + monster + " for 5 damage";
});
Working example : https://jsfiddle.net/DinoMyte/4dyph8jh/5/
Updated fiddle
Because you're using jQuery it could be simply :
$('#battle').click(function() {
$('#dam').text("You have hit the " + $('#monsters option:selected').text() + " for 5 damage");
});
Hope this helps.

Textarea value remain the same after submitting a form

My previous problem has been fixed, now I need to ask how to keep a textarea from resetting its input after a form is submitted. Here is the jsFiddle: http://jsfiddle.net/rz4pnumy/
Should I change the form in the HTML?
<form id="form1" method="GET">
(the form does not go into a php file or anything else, i'm using it to submit the textarea input and use the variables I made using jQuery to make a paragraph on the same page)
or something in the JS?
$(document).ready( function () {
$('#form1').on('submit', function (event) {
// If the form validation returns false, block the form from submitting by
// preventing the event's default behaviour from executing.
if (!validate()) {
event.preventDefault();
}
if(validate()) {
var adjective1 = $('#adjective1').val();
var adjective2 = $('#adjective2').val();
var pluralnoun = $('#plural-noun').val();
var verb1 = $('#verb1').val();
var edibleobject = $('#edible-object').val();
var monster1 = $('#monster1').val();
var adjective3 = $('#adjective3').val();
var monster2 = $('#monster2').val();
var verb2 = $('#verb2').val();
$('body').append(
'<div id="para">' +
'<p>Rain was still lashing the windows, which were now ' + adjective1 +', but inside all looked bright and cheerful. ' +
'The firelight glowed over the countless ' + adjective2 + '' + pluralnoun + ' where people sat ' + verb1 + ', talking, ' +
'doing homework or, in the case of Fred and George Weasley, trying to find out what would happen if you fed a ' + edibleobject +' to a ' + monster1 + '.' +
'Fred had "rescued" the ' + adjective3 + ', fire-dwelling ' + monster2 + ' from a Care of Magical Creatures class and it was now ' + verb2 + ' gently ' +
'on a table surrounded by a knot of curious people. </p>' +
'</div>'
);
}
});
function validate() {
var success = true;
$('.input').each(function(i, item) {
if ($(item).val() === "")
{
console.log("Missing textarea input");
success = false;
$(item).attr("style","border:1px solid red;");
//note it will overwrite your element style in all Input class
}
else
{
$(item).removeAttr('style')
// to remove border
}
});
return success;
}
});
The contents get emptied after pressing submit and I only see the completed paragraph for a split second.
You need to prevent the default event handler from executing whether validate passes or not, so you need to remove the if statement around the event.preventDefault() call. The preventDefault is the function that is keeping the from from submitting and re-loading your page.
Also, your Fiddle was not set to jQuery (it was set to no-library) so that may have also been causing you issues during your testing.
Edited for example of what I'm talking about:
$('#form1').on('submit', function (event) {
// block the form from submitting by
// preventing the event's default behaviour from executing.
event.preventDefault();
if(validate()) {
var adjective1 = $('#adjective1').val();
var adjective2 = $('#adjective2').val();
var pluralnoun = $('#plural-noun').val();
... etc ...
I would use php and set a variable to the GET value of the textarea and set the value of the textarea to that variable

Accept user input and multiply by 0.00000116414, copy results to clipboard

This code pops up asking for the users input, and multiplies it by 0.00000116414.
I want to change this into a text input field and calc button, then perhaps add the ability to copy to the clipboard. How might I do this?
<html>
<head>
<meta name="Recommended Share Difficulty Calculator" content="[Share Dicciculty Calculator]" />
<title>Recommended Share Difficulty</title>
<script type="text/javascript">
function MathThing()
{
input = prompt("Enter your max KH/s.", "");
if (input==null || input=="")
{
return false;
}
share = 0.00000116414 ;
total = input * share;
alert(input + " * " + share + " = " + total);
}
</script>
</head>
<body>
Calculate
</body>
</html>
In order to manipulate the contents of a users clipboard you will need to utilize Flash. There is a great helper library called ZeroClipboard. I've set up a basic demo (that uses your JavaScript) that uses this JavaScript:
var client = new ZeroClipboard(
$("#copy"), {
moviePath: "http://zeroclipboard.org/javascripts/zc/ZeroClipboard_1.3.2.swf"
});
client.on('dataRequested', function (client, args) {
client.setText((function () {
input = prompt("Enter your max KH/s.", "");
if (input == null || input == "") {
return;
}
share = 0.00000116414;
total = input * share;
alert('"'+input + " * " + share + " = " + total+'" copied to your clipboard');
return input + " * " + share + " = " + total;
})());
});
This code follows the examples provided in the Zero Clipboard, the odd thing is it doesn't seem to work 100% of the time. I do most of my work on computers that don't have Flash so I don't know if this reliability is part of the library or my computer. Good luck.
Copying cross-browser is tricky.
Here is some super-simple code showing an input + button use case:
var el = document.getElementById('input-id');
var sub = document.getElementById('submit-id');
var calc = function(e){
var q = el.value;
var share = 0.00000116414;
if (q.length > 0){
var res = q * share;
alert(res);
}
};
sub.addEventListener('click', calc);
Fiddle: http://jsfiddle.net/G6T76/3/
You'll probably want to do a bit more validation on the input, though.

onClick function not working in IE. Any ideas?

This code below works in every other browser bar IE. The code basically looks lets the uder pick a card, if it has, it chooses another card that hasn't been picked, and then adds it too an array. Unfortunately its not working in IE. No console errors.
Does anyone have any ideas?
Thanks
function getCard(clicked_id)
{
$("#frontCard").animate({
height:"-=600",
width:"-=250",
},1000,'easeOutElastic');
$("#frontCard").css("opacity",0);
clicked_id = "#" + clicked_id;
$(clicked_id).animate({ opacity: 0, left: "700px" }, 'slow');
$("#frontCard").animate({
height:"+=400",
width:"+=250",
},1000,'easeOutElastic');
$("#frontCard").css("opacity",1);
var newCard= Math.floor((Math.random()*13)+1);
var newSuit= Math.floor((Math.random()*4)+1);
var currentCard;
var x=document.getElementById("pick");
var rules=document.getElementById("rules");
var kings=document.getElementById("kings");
var currentCards=document.getElementById("currentCard");
if (cardsPicked.indexOf(numbers[newCard-1] + " " + suits[newSuit-1])== -1){
if (numbers[newCard-1]=="K" && king<4){
king=king+1;
}
if(king==4){
king= "All kings found!";
alert("Fourth king picked. Down the jug!");
}
cardsPicked.push(numbers[newCard-1] + " " + suits[newSuit-1] );
for (count=0; count<cardsPicked.length; count++)
currentRule = cardRules[newCard-1];
x.innerHTML=cardsPicked;
currentCards.innerHTML=numbers[newCard-1] + " " + suits[newSuit-1];
rules.innerHTML=currentRule;
kings.innerHTML=king;
}else{
getCard();
}
}
{
height:"-=600",
width:"-=250",
}
{
height:"+=400",
width:"+=250",
}
Remove the trailing , in each of your comma separated values in Objects.
I don't see the click event. But may be it helps:
Never overwrite the running event with innerHTML (in IE <10).

IE8 hangs after pressing "print" button in browser print dialogue when rendering content assembed with javascript via an iframe

I've been working on this issue for a couple weeks now and have been unable to resolve it. The problem is only reported by a small subset of IE8 users. I have attempted to reproduce the problem by running a VM of windows xp, IE8 (same version users report), and synced browser security settings. Despite this, I am unable to reproduce the problem for myself. Reproducing it would be great, but ultimately all that matters is discovering the source of the problem.
The way the print function works is:
User presses a link on the page which triggers a javascript function.
The javascript performs some logic to get the content of a subsection of the page (based on which print link was clicked).
"exCanvas elements are set to display:none" because I found that they caused printing bugs.
4.The element is printed using a slightly modified version of "Print Element" found here: http://projects.erikzaadi.com/jQueryPlugins/jQuery.printElement/
The user then is prompted with a print dialogue from IE. When the user hits the "print" button IE hangs and can only be shutdown by ending the process. If the user hits "cancel" IE does not hang and the user can continue about their business.
The user is able to use the default print functionality to print the entire page without trouble. It is only when they used my javascript based print function that the browser hangs.
I've had the user run no-addon IE8, look in their windows event log, and disable some common problem features in IE8.
I'm really stumped as to where in the process this error may be occuring. It seems to point to my javascript but it stumps me that the error occurs after the browser print dialogue print button is pressed. I would expect the error to occur before the window.print() function is called on the focused iframe.
Any help would be greatly appreciated as this bug has given me quite a bit of frustration.
Thanks.
EDIT----------------------------------------
I use the standard jquery print library above with a slightly custom _getMarkup function as seen below:
function _getMarkup(element, opts) {
var $element = $(element);
var elementHtml = _getElementHTMLIncludingFormElements(element);
var html = new Array();
html.push('<html><head><title>' + opts["pageTitle"] + '</title>');
if (opts["overrideElementCSS"]) {
if (opts["overrideElementCSS"].length > 0) {
for (var x = 0; x < opts["overrideElementCSS"].length; x++) {
var current = opts["overrideElementCSS"][x];
if (typeof (current) == 'string')
html.push('<link type="text/css" rel="stylesheet" href="' + current + '" >');
else
html.push('<link type="text/css" rel="stylesheet" href="' + current["href"] + '" media="' + current["media"] + '" >');
}
}
}
else {
$("link", document).filter(function () {
return $(this).attr("rel").toLowerCase() == "stylesheet";
}).each(function () {
html.push('<link type="text/css" rel="stylesheet" href="' + $(this).attr("href") + '" media="' + $(this).attr('media') + '" >');
});
}
//Ensure that relative links work
html.push('<base href="' + _getBaseHref() + '" />');
html.push(hieviews.getPrintCSS($("head").html()));
html.push('</head><body style="' + opts["printBodyOptions"]["styleToAdd"] + '" class="' + opts["printBodyOptions"]["classNameToAdd"] + '">');
var contentStr = $('<div></div>');
$(contentStr).append($('#disclaimer').html());
$(contentStr).append($('#nav').html());
$(contentStr).append("<hr/><h3 class='table-header'>"+$(".title",$(element).parent().parent().children(":first")).text() +"</h3>");
$(contentStr).append('<div>' + elementHtml + '</div>');
var refTable = "";
var total = $(".show-tooltip-text, .hidden_report",contentStr).each(function(index){
if(index == 0){
refTable += "<h3>Reference Table</h3><table class=\"dataTable\" id=\"cite\"><thead><tr><th>ref</th><th>Content</th></tr></thead><tbody>";
}
//if($(this).is(":hidden")){
if($(this).css("display") != "block"){
$(this).parent().append("<sup>*ref: #"+index+"</sup>");
refTable += "<tr><td>"+index+"</td><td>"+$(this).html()+"</td></tr>";
}
if(index == total){
refTable += "</tbody></table>";
}
}).length;
$(contentStr).append(refTable);
html.push($(contentStr).html());
html.push('<script type="text/javascript">function printPage(){focus();window.print();' + ((!$.browser.opera && !opts["leaveOpen"] && opts["printMode"].toLowerCase() == 'popup') ? 'close();' : '') + '}<\/script>');
html.push('</body></html>');
return html.join('');
};

Categories

Resources