I am a total beginner and am learning front-end using a "just do it" and project-focus route.
My web app will essentially work similar to that of a to-do list.
I assume it is because I have "getElementById" twice for the same element.
This works initially:
// add idea to list button
document.getElementById('btnSubmit').addEventListener("submitIdea", submitIdea);
function submitIdea() {
var ul = document.getElementsByClassName('anIdea')[0];
var enterIdea = document.getElementById('enterIdea');
var li = document.createElement('li');
li.setAttribute('class', enterIdea.value);
li.appendChild(document.createTextNode(enterIdea.value));
ul.prepend(li);
li.contentEditable = 'true';
};
But then, when I add this code, I am unable to write anything at all in my input box:
// use enter key to submit new li item
document.getElementById("enterIdea").addEventListener('keypress', function(event) {
event.preventDefault();
if (event.keyCode === 13) {
document.getElementById('btnSubmit').click();
}
});
These are the resources I used:
https://memorynotfound.com/dynamically-addremove-items-list-javascript/
Trigger a button click with JavaScript on the Enter key in a text box
your code is ok in general
document.getElementById('btnSubmit').addEventListener("click", function() {
var ul = document.getElementsByClassName("anIdea")[0];
var enterIdea = document.getElementById("enterIdea");
var li = document.createElement("li");
li.setAttribute('class', enterIdea.value);
li.contentEditable = "true";
li.appendChild(document.createTextNode(enterIdea.value));
ul.prepend(li);
});
document.getElementById("enterIdea").addEventListener("keypress", function(event) {
if (event.keyCode === 13) {
document.getElementById("btnSubmit").click();
}
});
Instead of trying to "click" the button with javascript, simply call the desired function on the enter key press.
document.addEventListener("keypress", function(event) {
event.preventDefault();
if (event.keyCode === 13) {
document.getElementById('btnSubmit').click();
}
});
Related
I am creating a to do list project in vanilla Javascript and have been trying to figure out how to edit an li item in the list on a double click mouse event. I want to be able to have the original text in the textbox after double clicking and update with the new text after clicking away from the textbox or pressing enter.
This is something I tried to write. Please let me know what I am doing wrong or if there is a better approach to the problem.
editInput function() {
var todosUl = document.querySelector('ul');
todosUl.addEventListener('dblclick', function(event) {
if (event.target.childNodes[0]) {
var originalInput = event.target.childNodes[0];
var editingInput = document.createElement("input");
editingInput.type = 'text';
parent = editingInput.parentNode;
parent.replaceChild(originalInput, editingInput);
}
Please no jQuery!
you can use contenteditabe property of html, and add the property on click to the desired element:
Object.prototype.insertAfter = function (newNode) {
this.parentNode.insertBefore(newNode, this.nextSibling);
};
document.addEventListener('keypress', function(e) {
if(e.currentTarget.activeElement.className === 'content'){
if ((e.keyCode || e.which) == 13) {
var li = document.createElement('li');
var ce = document.createAttribute('contenteditable');
ce.value = "true";
var cl = document.createAttribute('class');
cl.value='content';
li.setAttributeNode(ce);
li.setAttributeNode(cl);
e.currentTarget.activeElement.insertAfter(li);
li.focus();
return false;
}else{
return true;
}
}
});
li {
border: 1px solid #ccc;
}
<ul>
<li contenteditable="true" class="content">
</li>
This is a complete revision of my initial question, all unnecessary resources and references were deleted
I am tying the same event listener to 2 different elements: a button and Enter key, and it looks like the following:
var funcelement = function(){
//function code
};
$('#buttonID').click(funcelement);
$('#inputID').keyup(function () {
if (event.which == 13) {
$('#buttonID').trigger('click');
}
})
What I am trying to do is to prevent propagation of the enter key press if focus is on the submit button(#buttonID) by using preventDefault().
So I tried various combinations to make it work. The following is the latest result on my attempts
$('#inputID').keyup(function () {
var hasfocus = $('#buttonID').is(':focus') || false;
if (event.which == 13) {
if (!hasfocus) {
event.preventDefault();
$('#buttonID').trigger('click');
//hasfocus = true;
}
else {
//event.preventDefault();
//$('#buttonID').trigger('click');
}
}
})
After I enter a text into an input box and press Enter key, a confirmation window with yes/cancel buttons pops up with focus on yes button. Once I press Enter again, another window confirming that changes were made pops up with Ok button focused on it. Once I press Enter again, everything I need is being made.
However, there is one problem: after the last step is done, I am going back to the if (!hasfocus) line.
How do I prevent that from happening? Once the stuff I need is done - I don't want to go into that line again.
You can pass a parameter to into the function and stop the propagation there like so:
var funcelement = function(event, wasTriggeredByEnterKey){
if (wasTriggeredByEnterKey && $('#buttonID').is(':focus')) {
event.stopPropagation;
}
//function code
};
$('#buttonID').click(funcelement);
$('#inputID').keyup(function () {
if (event.which == 13) {
$('#buttonID').trigger('click', [true]);
}
}
)
UPDATE
In order to answer your revised issue, you should use the "keydown" event rather than "keyup" when working with alerts. This is because alerts close with the "keydown" event but then you are still triggering the "keyup" event when you release the enter key. Simply change the one word like this:
$('#inputID').keydown(function () {
var hasfocus = $('#buttonID').is(':focus') || false;
if (event.which == 13) {
if (!hasfocus) {
event.preventDefault();
$('#buttonID').trigger('click');
//hasfocus = true;
}
else {
//event.preventDefault();
//$('#buttonID').trigger('click');
}
}
})
I am using addEventListener to bind an event to a node. The addEventListener adds addItem function to node. But when I press enter the function is not running.
Here is the JavaScript:
document.getElementById('add-item').addEventListener('keypress', function (e) {
if (e.keyCode == 13) {
addItem();
}
}, false);
function addItem() {
var list = document.querySelector('ul.todo-list');
var newItem = document.getElementById('new-item-text').value;
var newListItem = document.createElement('li');
newListItem.className = 'todo-item';
newListItem.innerHTML = newItem + '<span class="remove"></span>';
list.insertBefore(newListItem, document.querySelector('.todo-new'));
//1. Empty the Input field once the item
document.getElementsByTagName('input')[0].value = '';
}
Here is the HTML:
<li class='todo-new'>
<input id='new-item-text' type='text'/>
<a id='add-item' href='#'>+</a>
</li>
On other hand the function runs with click
document.getElementById('add-item').addEventListener('click', addItem, false);
I want to do this with JavaScript only not using jQuery library.
Edited:
I want to attach the event to input field.
I'm willing to place a bet that the add-item element isn't in focus when you press enter. Instead, try changing the trigger to be the input field.
document.getElementById('new-item-text').addEventListener('keypress', function (e) {
if (e.keyCode == 13) {
addItem();
}
}, false);
I'm trying to add an autocomplete option to the title field in Wordpress - the titles of one of my custom document types will often (but not always) have a standard name.
I've hooked into Wordpress to add a div with an id of suggestions below title, and add a javascript onKeyUp event to title telling it to make an ajax request to a page that suggests names based on what's typed so far. This is all working fine.
Currently, however, I'm only able to select the suggestions via a mouseclick (which then uses val to update the value of #title. I'd also like users to be able to use the arrow keys to select a suggestion, a la Google.
I'm working on building this by giving each suggestion focus (each line is a li element with a dynamically generated tabindex.)
This works for a split second - the expected element gets the focus - but then it immediately loses it, going back to the body. Why is this happening?
Code for gethint.php:
<?php
$sofar = stripslashes($_GET['sofar']); // This is important as otherwise the url gets confused and won't work on anything with an apostrophe in it.
$common_file_names = array(
"Here's suggestion 1",
"This is suggestion 2",
"Suggestion 3");
if(strlen($_GET['sofar'])>1) { //Ignores single letters
echo '<ul id="autocomplete">';
$tabindex=0;
foreach ($common_file_names as $suggestion) {
if(false !== stripos($suggestion, $sofar)) : ?>
<li
tabindex="<?=$tabindex?>"
onClick="acceptSuggestion('<?=addslashes($suggestion)?>')"
onBlur="console.log('Lost focus!'); console.log(document.activeElement);";
><?=$suggestion?></li>
<?php $tabindex++; endif;
}
echo '</ul>';
}
?>
JS Code:
$.ajaxSetup({ cache: false });
window.onload = function () {
$( "<div id='suggestions'></div>" ).insertAfter( "#title" );
$(document).on('keydown', '#title', function (){
var hint_slash = this.value;
showHint(hint_slash);
checkKey(event);
});
$(document).on('focus', '#acf-field-extranet_client_area', function (){
clearSuggestions();
});
$(document).on('focus', '#acf-field-extranet_document_type', function (){
clearSuggestions();
});
$(document).on('focus', '#acf-date_picker', function (){
clearSuggestions();
});
$(document).on('focus', '#acf-file-value', function (){
clearSuggestions();
});
console.log("Scripts loaded successfully");
}
function showHint(str) { //If the user has typed 2 or more characters, this function looks for possible matches among common document names to speed up data entry.
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("suggestions").innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open("GET", "/gethint.php?sofar=" + str, true);
xmlhttp.send();
}
function acceptSuggestion(str) {
$('#title').val(str); //Puts the clicked suggestion into the title box.
clearSuggestions();
}
function clearSuggestions() {
showHint(""); //Clears suggestions.
}
function checkKey(event) {
console.log('Key press: ' + event.keyCode);
if(40 == event.keyCode) {
event.preventDefault(); // Stops scrolling.
var autocomplete = $("#autocomplete");
$(autocomplete.children('li:nth-child(' + 2 + ')')).focus() ;
console.log(document.activeElement);
}
}
This is just test code currently, hence always setting focus to the 3rd child element.
I wouldn't try focus on the suggestions. You'll have to add the keychecking code to every suggestion in this case, because the input will lose focus. Instead, create a CSS class for the "focused" suggestion, remove the class on key up/down and add it to the previous/next suggestion...
$input.keyup(function(e) {
if(e.which == 38) {
// up key
var active = $('.suggestions li.active');
if(active.length) {
active.removeClass('active');
active.prev().addClass('active');
} else {
$('.suggestions li:last').addClass('active');
}
} else if(e.which == 40) {
// down key
var active = $('.suggestions li.active');
if(active.length) {
active.removeClass('active');
active.next().addClass('active');
} else {
$('.suggestions li:first').addClass('active');
}
}
});
Building on #evilunix's answer, I realised that each keystroke was resetting the #suggestions div, which meant that it could never hold focus (or keep an appended class etc).
So, wrote a new function called checkKey:
function checkKey(e) {
if(e.which == 38) {
// up key
e.preventDefault(); //Stops scrolling and cursor movement.
var active = $('#suggestions li.active');
if(active.length) {
active.removeClass('active');
active.prev().addClass('active');
} else {
$('#suggestions li:last').addClass('active');
}
} else if(e.which == 40) {
// down key
e.preventDefault(); //Stops scrolling and cursor movement.
var active = $('#suggestions li.active');
if(active.length) {
active.removeClass('active');
active.next().addClass('active');
} else {
$('#suggestions li:first').addClass('active');
}
} else if(e.which == 13) {
//Return key
e.preventDefault(); //Stops form submission.
acceptSuggestion(document.getElementsByClassName('active')[0].innerHTML);
} else {
console.log(e.which);
showHint($('#title').val());
}
}
and changed #title's onKeydown event to:
$(document).on('keydown', '#title', function (){
checkKey(event);
});
Now #suggestions only refreshes if the keystroke is not an up arrow, down arrow or return, and on a return runs acceptSuggestion on whichever li has the active class.
I made simple web chat, bubles ( messages) above one text field (input message) and send button. How to make that input text field holds focus and not to lose when I click on something else (to focus always be on input with id="input_message") ?
var el = document.getElementById('input_message');
el.focus();
el.onblur = function () {
setTimeout(function () {
el.focus();
});
};
Here's the fiddle: http://jsfiddle.net/MwaNM/
Here's a dirty hack.
<input type="text" id="input_message" />
<script type="text/javascript">
with (document.getElementById('input_message')) {
onblur = function(e) {
var elm = e.target;
setTimeout(function(){elm.focus()});
}
onkeydown = function(e) {
var key = e.which || e.keyCode;
if (key == 9) e.preventDefault();
// code for tab is 9
}
}
</script>
var inputElement = document.getElementById("input_message");
inputElement.focus();
inputElement.addEventListener("blur", function(event){
inputElement.focus();
});
http://jsfiddle.net/653w1mpv/