Problem with changing button text content - javascript

I'm making a battleship game in Javascript and I have a problem with a function that changing button text content. I want to do that when the user click the button the text content of the button changes.
function changePosition(eventBtn){
if(eventBtn.target.textContent=='perpendicularly'){
eventBtn.target.textContent='horizontally';
}
else{
eventBtn.target.textContent='perpendicularly';
}}
But when I click on the button nothing changes. I think the problem is with the else statement because when I delete this statement all work.

Make sure that you are adding the listener to the button appropriately.
function changePosition(event) {
if (event.target.textContent === 'Perpendicularly') {
event.target.textContent = 'Horizontally';
} else {
event.target.textContent = 'Perpendicularly';
}
}
document.querySelector('.direction').addEventListener('click', changePosition);
<button class="direction">Perpendicularly</button>
In regards to the following statement:
But when I click on the button nothing changes. I think the problem is with the else statement because when I delete this statement all work.
Your event may be firing twice. It could be calling your event listener twice, effectively reverting the change it just made to the text.
Suggested improvement
Magic strings are bad, and I would recommend the use of enumerable values instead.
const Direction = {
PERPENDICULARLY: 'Perpendicularly',
HORIZONTALLY: 'Horizontally'
};
const changePosition = event => {
event.target.textContent =
event.target.textContent === Direction.PERPENDICULARLY
? Direction.HORIZONTALLY
: Direction.PERPENDICULARLY
};
document.querySelector('.direction').addEventListener('click', changePosition);
<button class="direction">Perpendicularly</button>

Related

How to replace attribute and keep it after callback executed in javascript?

I'm newbie in javascript. So, I need some help.
I have ASPxGridView on WebForm and I want to run my code when "Clear" button clicked. I mean embeded button in ASPxGridView, which placed in SearchPanel. So, I placed this code in javascript:
window.onload = function (s, e){
document.getElementById("gridFileList_DXCBtn1").removeAttribute("data-args");
document.getElementById("gridFileList_DXCBtn1").setAttribute("onclick", "gridFileList.PerformCallback();");
}
It works perfect, but after callback, when I click again on this button my code doesn't run again, I see, that this button has again its attribute "data-args" and has no my attribute "onclick".
Window.onload does not fired after callback, so can you explain me what event I need to use for decribed behavior on that button?
Ok, I found that the button looks like recreated each time, when it is pressed. So I made a trick. I wrote in body section
<body onclick="OnClick(event);">
and in script section:
function OnClick(e) {
if (e != undefined && e.target.className == "dx-vam" && e.target.localName == "span" && e.target.textContent == "Очистить") {
var btn = e.target.parentElement.parentElement;
if (btn.attributes[btn.attributes.length - 1].name == "data-args") {
btn.removeAttribute("data-args");
}
gridFileList.PerformCallback();
}
}

Toggle text in button onclick

I'm trying to toggle the text in a button every time it's clicked, between "READ" and "NOT READ". The buttons have been created dynamically with js and placed into an HTML table. Each button has a unique ID, but the same class name.
I've written an if statement that works for the first button that is set in the table, but the same if statement wont work for the buttons created dynamically.
I've tried lots of different variations for the if statements. I'm not sure if the best way would be to access the unique id's, but I don't know how to do that.
Any help is appreciated! Thanks
Here's a repl https://repl.it/repls/SpryVisibleMining
function toggleText(){
if (readButton.innerHTML == "READ"){
readButton.innerHTML = "NOT READ";
} else if (readButton.innerHTML == "NOT READ"){
readButton.innerHTML = "READ";
} else {
null
}
}
And this is if statement that wont wont do anything
function toggleOthers() {
let toggle = document.getElementsByClassName(".readBtn")
toggle[0].addEventListener("click", () => {
if (toggle.innerHTML == "READ") {
toggle.innerHTML = "NOT READ"
} else if (toggle.innerHTML == "NOT READ") {
toggle.innerHTML = "READ"
} else {
null
}
})
}
toggleOthers()
The problem lies in how you are listening for the click events. Your toggleText function is triggered whenever you click the #readed button with the onclick attribute. But inside the toggleText function you add another event listener to the same button, adding a new event listener every time you click the button.
So every time you click the button you increment the amount of times you are calling toggleText.
Remove the onclick from the button and change the id to a class attribute. You said you would have multiple buttons, so having multiple buttons with the same id won't do it.
<button class="readed">READ</button>
Because you want to listen for the click event on dynamically created elements I suggest you use Event Delegation. This means listening for the click event on a parent element, this could be your table#shelf element, and check which element has been clicked. If A has been clicked, then do X, if B has been clicked, then do Y.
Listen for click event on your table element.
var table = document.getElementById('shelf');
table.addEventListener("click", tableClickHandler);
In tableClickHandler check which element has been clicked. You can do it by getting the clicked target and use the closest method to see if it really is the element you want to be clicked.
For example when you would have a <span> in your <button>, event.target would be <span>. But you want the <button> element. closest goes up in the DOM tree to see if it finally reaches an element that is the <button> you want and returns it.
You can do this for any button inside of your table.
function tableClickHandler(event) {
var readed = event.target.closest('.readed');
if (readed) {
toggleText(readed);
}
}
Modify your toggleText function so that it can take any <button> you throw add it that you want the text toggled in. Add a button parameter which represents the current button.
// Toggle text when clicked.
function toggleText(button) {
if (button.innerHTML == "READ") {
button.innerHTML = "NOT READ";
} else if (button.innerHTML == "NOT READ") {
button.innerHTML = "READ";
} else {
null
}
}
For example you can use this:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<button onclick="toggle(this)">not read</button>
<script>
function toggle(e) {
let txt = e.innerText;
e.innerText = txt == 'not read' ? 'read' : 'not read';
}
</script>
</body>
</html>
Let me know if it's not suitable for your use case ...
And also you can use querySelectorAll() to get all buttons and then set this event with a for() loop.
Try
toggleText = b=> b.innerHTML = b.innerHTML=='READ'?'NOT READ':'READ'
<button id="A" onclick="toggleText(this)">NOT READ</button>
<button id="B" onclick="toggleText(this)">NOT READ</button>
According to your repl, you also registered an onclick-Handler on your button, too.
So calling toggleText() while clicking the "Read/Not-Read"-button, will effectively register another onclick-Handler. This will repeat as often as you press the button.
This will run as follows:
run onclick-Handler toggleText(); this will register another EventListener
run the EventListener (registered first by index.js)
run the new registered EventListener (registered by button.onclick)
rinse and repeat ...
Just remove it in your HTML:
<td><button id="readed">READ</button></td>
You have to init an array named books, and each time you add a new book, you have to push the new book to the books array.
And also you have to set a flag as hasReadBook to the Book class.
When you are going to render your table row you have to write an if, for making the flag to string in dom.
function updateTable() {
//anythings needs to done for updating table.
//for hasReadBook flag you should do like this:
const hasReadBookString = books[i].hasReadBook ? "Read" : "Not Read";
}
And you need to make a loop on readBtn HTML collection, to know which index is going to change:
let books = [{...}];
let toggles = document.getElementsByClassName(".readBtn");
for (var i = 0; i < toggles.length; i++){
labels[i].addEventListener('click', function(e) {
books[i].hasReadBook = !books[i].hasReadBook;
})
}
updateTable();

Disable a table cell after the first click in javascript

I have a table cell as the following :
<td id=report onMouseUp='clickReport()' onKeyPress='clickReport()' >Click</td>";
The event function is as below :
function clickReport() {
document.form.submit();
}
On form submission, there is a back-end process going on. Until the 1st process completes(i.e., until the page reloads), I do not want the user to press the press the "Click" again, else it may affect the previous running process.
So, I thought of disabling the "Click" after the first press.
I tried using preventDefault() but it is not working.
function clickReport() {
document.form.submit();
document.getElementById("report").onMouseUp = function(e)
{
e.preventDefault();
return false;
}
document.getElementById("report").onKeyPress = function(e)
{
e.preventDefault();
return false;
}
}
Can someone please help!
1) You might pass the element parameter to your event functions, so you can acces the DOM element easily. See below.
<td id=report onMouseUp='clickReport(this)' onKeyPress='clickReport(this)' >Click</td>";
2) On the first function run you might null the events, so they will not fire anymore. See below.
// the *element* parameter is yor <td> element here
function clickReport(element) {
document.form.submit();
element.onMouseUp = null;
element.onKeyPress= null;
}
3) You might use onclick event instead of onmouseup and get rid of onkeypress, if you only want to make it work on click.
<td id=report onclick='clickReport(this)'>Click</td>";
function clickReport(element) {
document.form.submit();
element.onclick= null;
}
Working codepen: https://codepen.io/anon/pen/MmVNMe
this should work.
since at first the disableClick is undefined the click will fire, as soon as it fires the flag will be set to true and the click will no longer be possible.
<td id=report onMouseUp='!disableClick && clickReport()'
onKeyPress='!disableClick && clickReport()' >Click</td>"
function clickReport() {
document.form.submit();
window.disableClick = true;
}

Problem with event.target in IE

I'm writing js for a status update system to be used on various pages throughout a app that I'm working. I am really just starting to get more comfortable with javascript so it has been somewhat of a challenge to get to the point where I have everything now.
The status system is basically a facebook clone. For the most part everything is supposed to function the way that facebook's status updates and status comments do. The intended behavior is that when the user clicks in the status textarea, the div under the status textarea slides out revealing the submit button as well as some other checkboxes.
If the user clicks anywhere else on the page except a link or any element that has the class prevent_slideup the div slides up hiding the submit button and any checkboxes.
I'm using a document.body click function to determine what the user clicked on so I know which form elements to hide if I should even hide them. I do not want this slideup to take place on a textarea if that textarea has focus or the user is selecting a checkbox that goes with that form. Hence the prevent_slideup class. I also do not want to bother running the slideup logic if the user has clicked on a link. I'd prefer they just leave the page without having to wait for the animation.
The code that I was using to accomplish this task can be found in the $(document.body).click(function (e) section below where I'm doing a .is('a') check on the event target.
This code works as expected in chrome and firefox, however in ie when a link is clicked for the first time it seems that the element stored in var target is actually a div instead of an anchor. What ends up happening is that the submit div slides up and the user is not taken to the link that they just clicked on. If a link is clicked a second time the user is taken to the page as you would expect.
It seems to me that there's some kind of a lag in ie as to what the current event being fired is.
The entire status module is working other than this one strange ie bug regarding the users click on the link not being carried out the first time that they click a link after opening the status textarea. Does anything jump out in this script that would explain this behavior or does anyone have any other advice?
Thanks in advance for your help.
$(document).ready(function(){
$("textarea.autoresize").autoResize();
});
$(document.body).click(function (e){
var target = e.target || e.srcElement;
console.log(target);
console.log($(target).is('a'));
if($(target).hasClass('prevent_slideup') || $(target).is('a'))
{
return true;
}
else
{
var active_element = document.activeElement;
var active_status_id = $(active_element).attr('data-status_id');
var active_has_data_status_id = (typeof active_status_id !== 'undefined' && active_status_id !== false) ? true : false;
$('textarea').each(function(){
if($(this).hasClass('status_comment_textarea'))
{
var status_id = $(this).attr('data-status_id');
if($('#comment_textarea_'+status_id).val() === '' && (!active_has_data_status_id || active_status_id !== status_id))
{
hide_status_comment_submit(status_id);
}
}
else if($(this).attr('id') === 'status_textarea')
{
if($('#status_textarea').val() === '' && $(active_element).attr('id') !== 'status_textarea')
{
$('#status_textarea').html($("#status_textarea").attr('placeholder'));
hide_status_submit();
}
}
});
return true;
}
});
$("#status_textarea").live('click', function(){
if($('#status_textarea').val() === $("#status_textarea").attr('placeholder'))
{
$('#status_textarea').html('');
}
show_status_submit();
return false;
});
$(".comment_toggle").live('click', function(){
var status_id = $(this).attr('data-status_id');
show_status_comment_submit(status_id);
return false;
});
$(".status_comment_submit").live('click', function(){
var status_id = $(this).attr('data-status_id');
$('#status_comment_submit_wrapper_'+status_id).addClass('status_comment_submit_successful');
return false;
});
$(".show_hidden_comments").live('click', function(){
var status_id = $(this).attr('data-status_id');
$('#status_hidden_comments_'+status_id).show();
$(this).hide();
return false;
});
function hide_status_submit()
{
$("#status_textarea").removeAttr('style');
$("#status_textarea").blur();
$("#status_block").removeClass('padding_b10');
$("#status_submit_wrapper").slideUp("fast");
return false;
}
function show_status_submit()
{
if ($("#status_submit_wrapper").is(":hidden"))
{
$("#status_block").addClass('padding_b10');
$("#status_submit_wrapper").slideDown('fast');
}
return false;
}
function hide_status_comment_submit(status_id)
{
if(!$('#status_comment_submit_wrapper_'+status_id).is(":hidden"))
{
$('#status_comment_submit_wrapper_'+status_id).hide();
$('#fake_comment_input_'+status_id).show();
$('#comment_textarea_'+status_id).removeAttr('style');
}
return false;
}
function show_status_comment_submit(status_id)
{
if($('#status_comment_submit_wrapper_'+status_id).is(":hidden"))
{
$('#fake_comment_input_'+status_id).hide();
$('#status_comment_submit_wrapper_'+status_id).show();
$('#comment_textarea_'+status_id).focus();
}
return false;
}
function status_comment_submit_successful()
{
hide_status_comment_submit($('.status_comment_submit_successful').attr('data-status_id'));
$('.status_comment_submit_successful').removeClass('status_comment_submit_successful');
return false;
}
I figured out that there were two main issues with my script...
1.) The document.body function and the #status_textarea live click funtioins were conflicting with each other.
2.) After adding the logic for the #status_textarea function into the document.body function I noticed that the script still didn't quite work as expected in internet explorer unless I had an alert in the function. The problem at this point was that the autoresize plugin that I'm using on the textarea was also conflicting with the document.body function.
I was able to rectify the situation by adding a dummy text input and hiding the status textarea. On click of the dummy text input the status textarea is shown and the the dummy text input is hidden. I have no idea why this worked, but it seems to have solved my problems.

ASP.NET Post-Back and window.onload

I got a function which checks if some input fields are changed:
var somethingchanged = false;
$(".container-box fieldset input").change(function() {
somethingchanged = true;
});
And a function which waits on window.onload and fires this:
window.onbeforeunload = function(e) {
if (somethingchanged) {
var message = "Fields have been edited without saving - continue?";
if (typeof e == "undefined") {
e = window.event;
}
if (e) {
e.returnValue = message;
}
return message;
}
}
But if I edit some of the fields and hit the save button, the event triggers, because there is a post-back and the fields have been edited. Is there anyway around this, so the event does not fire upon clicking the save button?
Thanks
When I do this pattern I have a showDirtyPrompt on the page. Then whenever an action occurs which I don't want to go through the dirty check I just set the variable to false. You can do this on the client side click event of the button.
The nice thing about this is that there might be other cases where you don't want to prompt, the user you might have other buttons which do other post backs for example. This way your dirty check function doesn't have to check several buttons, you flip the responsability around.
<input type="button" onclick="javascript:showDirtyPrompt=false;".../>
function unloadHandler()
{
if (showDirtyPrompt)
{
//have your regular logic run here
}
showDirtyPrompt=true;
}
Yes. Check to see that the button clicked is not the save button. So it could be something like
if ($this.id.not("savebuttonID")) {
trigger stuff
}

Categories