I'm working on a choose your own adventure game written entirely in HTML and Javascript; I want to create most of my elements entirely in Javascript to create an awesome dynamic game! I am having trouble using events and event listeners. It's a mystery game; after the player chooses their character from a list, they can invite five guests to a party. One of the guests is killed, leaving you to solve the mystery with three suspects.
After you've selected your player, there's another button that says "Select this character!". When this button is clicked, the player creation UI is supposed to be hidden, and a new UI is visible. With the code as it is now, the "StartGame" function is skipped entirely. What am I doing wrong? Any help you can give would be seriously awesome and greatly appreciated!
btnPlayer = document.createElement('button');
btnPlayer.id = 'BTN_btnPlayer';
btnPlayer.type = 'button';
btnPlayer.addEventListener('click', welcomePlayer(), true);
btnPlayer.onclick = welcomePlayer();
btnPlayer.innerHTML = 'Select This Character!';
myDiv.appendChild(btnPlayer);
EDIT
I modified my button event properties to look like this:
btnPlayer.addEventListener('click', welcomePlayer, true);
//btnPlayer.onclick = welcomePlayer;
One is commented out because neither has worked. I tried clearing my cache, too. Here is my StartGame() function with the button code excluded. I won't include the "charFirstNames[]" and "charLastNames[]" used to create the choices in my dropdownlist. I have them separated in order to tell a more interesting story; they will eventually be database records when I get the bugs and the basics worked out. I don't think I messed up anything up here, but is it possible that I did? The function is called by the only button coded into the HTML.
function startGame(divName) {
myDiv = document.getElementById('story');
lblPlayer = document.createElement('label');
lblPlayer.id = 'LBL_Player';
lblPlayer.htmlFor = 'DDL_PlayerChar';
lblPlayer.innerHTML = 'Please select a character. ';
myDiv.appendChild(lblPlayer);
ddlPlayer = document.createElement('select');
ddlPlayer.id = 'DDL_PlayerChar';
myDiv.appendChild(ddlPlayer);
defOpt = document.createElement("option");
defOpt.value = 0;
defOpt.text = 'Select...';
ddlPlayer.appendChild(defOpt);
//Create and append the options
for (var i = 0; i < charFirstNames.length; i++) {
var option = document.createElement("option");
option.value = charFirstNames[i]+'_'+charLastNames[i];
option.text = charFirstNames[i]+' '+charLastNames[i];
ddlPlayer.appendChild(option);
}
document.getElementById('BTN_Start').hidden = true;
}
The welcomePlayer() function is similar to the startgame() function, creating the interface to invite the first "guest" and removing the player creation UI.
Both of these lines set the onclick handler to the result of calling the welcomePlayer function (see the parens?).
btnPlayer.addEventListener('click', welcomePlayer(), true);
btnPlayer.onclick = welcomePlayer();
You probably mean
btnPlayer.addEventListener('click', welcomePlayer, true);
Related
this is my first question, so apologies if not written clearly.
I want to dynamically toggle a comment form after reply button is pressed. There are multiple comments (in below example three) to which a form (with different id) can be rendered separately.
I am able to do this with static id for form but not with dynamically defined id...
I have tried this static approach and this works fine.
var functs_t = {};
functs_t['fun_27'] = $('#reply_comment_id_27').click(function() {$('#form_comment_id_27').toggle('slow');});
functs_t['fun_23'] = $('#reply_comment_id_23').click(function() {$('#form_comment_id_23').toggle('slow');});
functs_t['fun_21'] = $('#reply_comment_id_21').click(function() {$('#form_comment_id_21').toggle('slow');});
However, I am having struggling with a dynamic approach.
var i;
var functs = {};
for (i=0; i<comment_qs_id_list.length; i++) {
var comment_id = comment_qs_id_list[i].toString();
var reply_comment_id = 'reply_comment_id_'+ comment_id;
var form_comment_id = $('#'+reply_comment_id).attr('name');
// works >>> toggles comment 27
functs['func_reply_comment_'+comment_qs_id_list[i]] = $('#reply_comment_id_'+comment_qs_id_list[i]).click(function() {$('#'+'form_comment_id_27').toggle('slow');});
// does not work
//functs['func_reply_comment_'+comment_qs_id_list[i]] = $('#reply_comment_id_'+comment_qs_id_list[i]).click(function() {$('#'+form_comment_id).toggle('slow');});
// works >> toggles everything (but what I want is to hide initially and only toggle after clicking reply button)
//$('#'+form_comment_id).toggle('slow');
};
Thanks so much!
I am just getting started on learning to code and am trying to create a game of checkers with what I have learned. After learning to back up my original attempt the hard way, I have restarted and am applying what I have learned since my original attempt by creating my board and checker pieces dynamically with JS.
The problem I am running into this time around is when it comes to adding eventListeners to my checkers. I have successfully gotten them to function as buttons and can get the assigned function to run when i click the button (although it runs every time I run the code as well), but I want to have the button return it's own ID when clicked so that I can use it in the functions that will move the checker pieces. I'm probably in a little over my head as I've only been learning for a couple of weeks but I don't want to give up on the dynamically created pieces just yet. Any help is appreciated. Here are my functions that I've written (any advice is welcome):`
function addElement(parent, newTag, newId, html, newClass){
var p = document.getElementById(parent);
var newElement = document.createElement(newTag);
newElement.setAttribute('id', newId);
newElement.innerHTML = html
newElement.setAttribute('class', newClass)
p.appendChild(newElement);
}
function addOnclick(checkerId, func){
var checker = document.getElementById(checkerId);
checker.onclick = func;
checker.addEventListener("onClick", func);
}
function returnId(id){
console.log(id);
}'''
This is where I attach the event to each piece:
for( i = 10; i<90; i++){
if (i % 10 === 0 || i % 10 === 9){addElement("board", "div", "s"+i, "X", "dummySquare")
} //select non "dummy" squares//
else{
var button = 0;
var x = "s"+i;
addElement("board", "div", "s"+i, "", "square" );
if(startingPosition.indexOf(x)>-1){
if (i<50){
addElement("s"+i, "button", "b"+i, "x", "checker")
document.getElementById("b"+i).classList.add("redChecker")
};
if (i>50){
addElement("s"+i, "button", "b"+i, "x", "checker")
document.getElementById("b"+i).classList.add("blackChecker")
};
// starting checkers added//
addOnclick("b"+i, returnId)
EDIT
After getting the onclick event to work, I am wanting to return the id property of the button in question: my thoughts were to try to call target the id property directly, then return it (log it just to make sure that it is functional first) but my approach is not doing the trick. It seems that the id argument is null and I'm not sure why.
function returnId(id){
element = document.getElementById(id);
elementId = element.id;
console.log(elementId)
}
I am currently creating a program which utilizes localStorage to create a site with a wishlist like functionality. However when I go to generate the html page that should create the wishlist with the photo of the item, the name and a button to remove said item from the list. But when I go to assign the onClick functionality to the button, the function fires on page load rather then on click. I have four main java script functions, one to add to the localstorage, one to remove from local storage, a helper function for removing and the one that will generate the wishlist page (where the problem is).
function genWishListPage(){
for (var i = 0; i < localStorage.length; i++) {
var item = getWishlist(i);
var name = document.createElement("p");
var removeButton = document.createElement("button");
var image = document.createElement("img")
image.src = item.image;
removeButton.innerText = "Remove from wishlist";
removeButton.onClick = RemoveFromWishList(item.name);
removeButton.setAttribute("ID","remove");
name.innerText = item.name;
document.body.appendChild(image);
document.body.appendChild(name);
document.body.appendChild(removeButton);
document.body.appendChild(document.createElement("BR"));
//removeButton.setAttribute("onclick", RemoveFromWishList(item.name));
//removeButton.addEventListener('click', RemoveFromWishList(item.name));
//document.getElementById("remove").addEventListener("click",RemoveFromWishList(item.name));
}
}
The commented parts are ways I have already tried and gotten the same bug.
Any help or advice is appreciated.
When you write
removeButton.onClick = RemoveFromWishList(item.name); you are assigning the return value of the function call to the onClick event. Instead you can write
removeButton.onClick = function() { RemoveFromWishList(item.name);}
You should assign a function to the onClick event listener.
first, the prototype:
function Notification (title, message, id) {
var $title = this.title = title;
var $message = this.message = message;
var $id = this.id = title;
/* ---------------creating HTML prototype */
var $mainDiv = $("<div></div>").appendTo($("#wrapper"));
$mainDiv.attr('id', $id);
$mainDiv.addClass('main-div');
var $dismissButton = $("<button>X</button>").appendTo($mainDiv);
$dismissButton.attr('id', 'dismissButton');
var $pTitle = $("<h2></h2>").appendTo($mainDiv);
$pTitle.attr('id', 'title');
$pTitle.text($title);
var $para = $("<p></p>").appendTo($mainDiv);
$para.attr('id', 'message');
$para.text($message);
var $ul = $("<ul></ul>").appendTo($mainDiv);
var $li1 = $("<li></li>").appendTo($ul);
$li1.attr('id', 'okButton');
var $button = $("<button>Ok</button>").appendTo($li1);
$button.addClass('buttons');
/* ---------------Dismissing notifications */
$("#dismissButton").click(function() {
document.getElementById($id).remove();
});
};
So, the prototype is made using new Notification(*arguments here*) and there we get a box with a notification widget. so far so good.
when i press the X button (id dismissbutton) it should remove the box, and it does.
However. if i use the new notification several times i get several boxes (with different ids for the $mainDiv) with their dismiss buttons not working. the upmost widget box's dismiss button is the only one that works, and it deleted all the other boxes as well.
I need to seperate them and have the dismiss button working for each box seperately.
thanks in advance :)
The problem here is that you are creating multiple elements with the same ID (which is invalid HTML by the way).
Every time your run
var $dismissButton = $("<button>X</button>").appendTo($mainDiv);
$dismissButton.attr('id', 'dismissButton')
A new "dismiss button" is being created, which has the same ID (dismissButton) with the previous "dismiss buttons" (if any).
The other thing is that every time you run
$("#dismissButton").click(function() {
document.getElementById($id).remove();
});
You instruct only the first "dismiss button" to remove the element identified by the ID $id when clicked.
In my opinion the best way to fix this is by using references to the elements themselves and not IDs.
So I would make the creation of the dismiss button like this;
var $dismissButton = $("<button>X</button>").appendTo($mainDiv);
And determine its click callback like this
$dismissButton.on('click', function () {
$mainDiv.remove();
});
This should work fine for you.
Last, but not least I would avoid giving the same ID to any elements, since it produces invalid HTML code. You are doing so in the following lines
$dismissButton.attr('id', 'dismissButton');
$pTitle.attr('id', 'title');
$para.attr('id', 'message');
$li1.attr('id', 'okButton');
I'm going to develop a firefox extension which adds a button beside the file input fields (the <input type="file"> tag) when a file is selected.
The file overlay.js, which contains the extension's logic, manages the "file choose" event through this method:
var xpitest = {
...
onFileChosen: function(e) {
var fileInput = e.explicitOriginalTarget;
if(fileInput.type=="file"){
var parentDiv = fileInput.parentNode;
var newButton = top.window.content.document.createElement("input");
newButton.setAttribute("type", "button");
newButton.setAttribute("id", "Firefox.Now_button_id");
newButton.setAttribute("value", "my button");
newButton.setAttribute("name", "Firefox.Now_button_name");
parentDiv.insertBefore(newButton, fileInput);
}
}
...
}
window.addEventListener("change", function(e) {xpitest.onFileChosen(e)},false);
My problem is that, everytime I choose a file, a new button is being added, see this picture:
http://img11.imageshack.us/img11/5844/sshotn.png
If I select the same file more than once, no new button appears (this is correct).
As we can see, on the first file input, only one file has been selected.
On the second one I've chosen two different files, in effect two buttons have been created...
On the third, I've chosen three different files.
The correct behavior should be this:
when a file is chosen, create my_button beside the input field
if my_button exists, delete it and create another one (I need this, beacuse I should connect it to a custom event which will do something with the file name)
My question is: how can I correctly delete the button? Note that the my_button html code does not appear on page source!
Thanks
Pardon me if I'm thinking too simply, but couldn't you just do this?
var button = document.getElementById('Firefox.Now_button_id')
button.parentNode.removeChild(button)
Is this what you were looking for? Feel free to correct me if I misunderstood you.
Solved. I set an ID for each with the following method:
onPageLoad: function(e){
var inputNodes = top.window.content.document.getElementsByTagName("input");
for(var i=0; i<inputNodes.length; i++){
if(inputNodes[i].type=="file")
inputNodes[i].setAttribute("id",i.toString());
}
}
I call this method only on page load:
var appcontent = document.getElementById("appcontent"); // browser
if(appcontent)
appcontent.addEventListener("DOMContentLoaded", xpitest.onPageLoad, true);
Then I've modified the onFileChosen method in this way:
onFileChosen: function(e) {
var fileInput = e.explicitOriginalTarget;
if(fileInput.type=="file"){
var parentDiv = fileInput.parentNode;
var buttonId = fileInput.id + "Firefox.Now_button_id";
var oldButton = top.window.content.document.getElementById(buttonId);
if(oldButton!=null){
parentDiv.removeChild(oldButton);
this.count--;
}
var newButton = top.window.content.document.createElement("input");
newButton.setAttribute("type", "button");
newButton.setAttribute("id", buttonId);
newButton.setAttribute("value", "my button");
newButton.setAttribute("name", "Firefox.Now_button_name");
parentDiv.insertBefore(newButton, fileInput);
this.count++;
}
}